@anvil-works/anvil-cli 0.5.1 → 0.5.3
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 +42 -16
- package/dist/cli.js +1844 -1230
- package/dist/index.js +23 -23
- package/package.json +1 -1
- package/scripts/install/install.cmd +8 -1
- package/scripts/install/install.ps1 +11 -1
- package/scripts/install/install.sh +10 -1
package/dist/cli.js
CHANGED
|
@@ -34509,7 +34509,7 @@ var __webpack_exports__ = {};
|
|
|
34509
34509
|
};
|
|
34510
34510
|
const eraseLine = ESC + '2K';
|
|
34511
34511
|
const eraseLines = (lines)=>lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : '';
|
|
34512
|
-
const
|
|
34512
|
+
const screen_manager_height = (content)=>content.split('\n').length;
|
|
34513
34513
|
const lastLine = (content)=>content.split('\n').pop() ?? '';
|
|
34514
34514
|
class ScreenManager {
|
|
34515
34515
|
height = 0;
|
|
@@ -34538,12 +34538,12 @@ var __webpack_exports__ = {};
|
|
|
34538
34538
|
if (rawPromptLine.length % width === 0) content += '\n';
|
|
34539
34539
|
let output = content + (bottomContent ? '\n' + bottomContent : '');
|
|
34540
34540
|
const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
|
|
34541
|
-
const bottomContentHeight = promptLineUpDiff + (bottomContent ?
|
|
34541
|
+
const bottomContentHeight = promptLineUpDiff + (bottomContent ? screen_manager_height(bottomContent) : 0);
|
|
34542
34542
|
if (bottomContentHeight > 0) output += cursorUp(bottomContentHeight);
|
|
34543
34543
|
output += cursorTo(this.cursorPos.cols);
|
|
34544
34544
|
this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
|
|
34545
34545
|
this.extraLinesUnderPrompt = bottomContentHeight;
|
|
34546
|
-
this.height =
|
|
34546
|
+
this.height = screen_manager_height(output);
|
|
34547
34547
|
}
|
|
34548
34548
|
checkCursorPos() {
|
|
34549
34549
|
const cursorPos = this.rl.getCursorPos();
|
|
@@ -37768,20 +37768,20 @@ var __webpack_exports__ = {};
|
|
|
37768
37768
|
}), mod);
|
|
37769
37769
|
function pathspec(...paths) {
|
|
37770
37770
|
const key = new String(paths);
|
|
37771
|
-
|
|
37771
|
+
esm_cache.set(key, paths);
|
|
37772
37772
|
return key;
|
|
37773
37773
|
}
|
|
37774
37774
|
function isPathSpec(path) {
|
|
37775
|
-
return path instanceof String &&
|
|
37775
|
+
return path instanceof String && esm_cache.has(path);
|
|
37776
37776
|
}
|
|
37777
37777
|
function toPaths(pathSpec) {
|
|
37778
|
-
return
|
|
37778
|
+
return esm_cache.get(pathSpec) || [];
|
|
37779
37779
|
}
|
|
37780
|
-
var
|
|
37780
|
+
var esm_cache;
|
|
37781
37781
|
var init_pathspec = __esm({
|
|
37782
37782
|
"src/lib/args/pathspec.ts" () {
|
|
37783
37783
|
"use strict";
|
|
37784
|
-
|
|
37784
|
+
esm_cache = /* @__PURE__ */ new WeakMap();
|
|
37785
37785
|
}
|
|
37786
37786
|
});
|
|
37787
37787
|
var GitError;
|
|
@@ -42572,6 +42572,57 @@ var __webpack_exports__ = {};
|
|
|
42572
42572
|
if (preferredEditors.includes(normalized)) return preferredEditorCommandByValue[normalized];
|
|
42573
42573
|
return preferredEditorValue;
|
|
42574
42574
|
}
|
|
42575
|
+
function extractExecutableFromCommand(command) {
|
|
42576
|
+
const trimmed = command.trim();
|
|
42577
|
+
if (!trimmed) return "";
|
|
42578
|
+
if (trimmed.startsWith('"')) {
|
|
42579
|
+
const closingIndex = trimmed.indexOf('"', 1);
|
|
42580
|
+
return closingIndex > 1 ? trimmed.slice(1, closingIndex) : "";
|
|
42581
|
+
}
|
|
42582
|
+
if (trimmed.startsWith("'")) {
|
|
42583
|
+
const closingIndex = trimmed.indexOf("'", 1);
|
|
42584
|
+
return closingIndex > 1 ? trimmed.slice(1, closingIndex) : "";
|
|
42585
|
+
}
|
|
42586
|
+
const firstSpace = trimmed.search(/\s/);
|
|
42587
|
+
return -1 === firstSpace ? trimmed : trimmed.slice(0, firstSpace);
|
|
42588
|
+
}
|
|
42589
|
+
function canExecutePath(filePath) {
|
|
42590
|
+
try {
|
|
42591
|
+
external_fs_.accessSync(filePath, "win32" === process.platform ? external_fs_.constants.F_OK : external_fs_.constants.X_OK);
|
|
42592
|
+
return true;
|
|
42593
|
+
} catch {
|
|
42594
|
+
return false;
|
|
42595
|
+
}
|
|
42596
|
+
}
|
|
42597
|
+
function isCommandAvailable(command, env = process.env) {
|
|
42598
|
+
const executable = extractExecutableFromCommand(command);
|
|
42599
|
+
if (!executable) return false;
|
|
42600
|
+
const hasPathSeparator = executable.includes(external_path_default().sep) || executable.includes("/");
|
|
42601
|
+
if (hasPathSeparator) return canExecutePath(executable);
|
|
42602
|
+
const pathEnv = env.PATH || "";
|
|
42603
|
+
if (!pathEnv) return false;
|
|
42604
|
+
const pathEntries = pathEnv.split(external_path_default().delimiter).filter(Boolean);
|
|
42605
|
+
const pathext = (env.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean);
|
|
42606
|
+
const extensions = "win32" === process.platform ? pathext : [
|
|
42607
|
+
""
|
|
42608
|
+
];
|
|
42609
|
+
const hasKnownExtension = "win32" === process.platform && pathext.some((ext)=>executable.toUpperCase().endsWith(ext.toUpperCase()));
|
|
42610
|
+
for (const dir of pathEntries){
|
|
42611
|
+
if ("win32" === process.platform && hasKnownExtension) {
|
|
42612
|
+
const candidate = external_path_default().join(dir, executable);
|
|
42613
|
+
if (canExecutePath(candidate)) return true;
|
|
42614
|
+
continue;
|
|
42615
|
+
}
|
|
42616
|
+
for (const ext of extensions){
|
|
42617
|
+
const candidate = external_path_default().join(dir, `${executable}${ext}`);
|
|
42618
|
+
if (canExecutePath(candidate)) return true;
|
|
42619
|
+
}
|
|
42620
|
+
}
|
|
42621
|
+
return false;
|
|
42622
|
+
}
|
|
42623
|
+
function getInstalledPreferredEditors() {
|
|
42624
|
+
return preferredEditors.filter((editor)=>isCommandAvailable(getPreferredEditorCommand(editor)));
|
|
42625
|
+
}
|
|
42575
42626
|
function getAllConfig() {
|
|
42576
42627
|
return config_config.store;
|
|
42577
42628
|
}
|
|
@@ -42878,13 +42929,15 @@ var __webpack_exports__ = {};
|
|
|
42878
42929
|
name: "value",
|
|
42879
42930
|
message,
|
|
42880
42931
|
choices,
|
|
42881
|
-
default: defaultValue
|
|
42932
|
+
default: defaultValue,
|
|
42933
|
+
loop: false
|
|
42882
42934
|
}
|
|
42883
42935
|
]);
|
|
42884
42936
|
return answer.value;
|
|
42885
42937
|
}
|
|
42886
42938
|
}
|
|
42887
42939
|
const external_readline_namespaceObject = require("readline");
|
|
42940
|
+
var external_readline_default = /*#__PURE__*/ __webpack_require__.n(external_readline_namespaceObject);
|
|
42888
42941
|
/*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */ function isNothing(subject) {
|
|
42889
42942
|
return null == subject;
|
|
42890
42943
|
}
|
|
@@ -47403,6 +47456,37 @@ var __webpack_exports__ = {};
|
|
|
47403
47456
|
throw errors_createNetworkError.network(error.message);
|
|
47404
47457
|
}
|
|
47405
47458
|
}
|
|
47459
|
+
async function listAppsForCheckout(options = {}) {
|
|
47460
|
+
const anvilUrl = options.anvilUrl ?? anvil_api_getDefaultAnvilUrl();
|
|
47461
|
+
const authToken = await auth_getValidAuthToken(anvilUrl, options.username);
|
|
47462
|
+
const params = new URLSearchParams();
|
|
47463
|
+
if ("number" == typeof options.limit) params.set("limit", String(options.limit));
|
|
47464
|
+
if (options.cursor) params.set("cursor", options.cursor);
|
|
47465
|
+
if (options.q && options.q.trim()) params.set("q", options.q.trim());
|
|
47466
|
+
const query = params.toString();
|
|
47467
|
+
const url = `${anvilUrl}/ide/api/_/apps${query ? `?${query}` : ""}`;
|
|
47468
|
+
try {
|
|
47469
|
+
const resp = await fetch(url, {
|
|
47470
|
+
method: "GET",
|
|
47471
|
+
headers: {
|
|
47472
|
+
Authorization: `Bearer ${authToken}`
|
|
47473
|
+
},
|
|
47474
|
+
signal: options.signal
|
|
47475
|
+
});
|
|
47476
|
+
if (!resp.ok) {
|
|
47477
|
+
if (401 === resp.status) throw errors_createAuthError.invalid("Authentication failed");
|
|
47478
|
+
throw errors_createNetworkError.server(resp.status, resp.statusText);
|
|
47479
|
+
}
|
|
47480
|
+
const data = await resp.json();
|
|
47481
|
+
return {
|
|
47482
|
+
apps: Array.isArray(data.apps) ? data.apps : [],
|
|
47483
|
+
next_cursor: "string" == typeof data.next_cursor ? data.next_cursor : null
|
|
47484
|
+
};
|
|
47485
|
+
} catch (error) {
|
|
47486
|
+
if (error.type) throw error;
|
|
47487
|
+
throw errors_createNetworkError.network(error.message);
|
|
47488
|
+
}
|
|
47489
|
+
}
|
|
47406
47490
|
function getGitFetchUrl(appId, authToken, anvilUrl = anvil_api_getDefaultAnvilUrl()) {
|
|
47407
47491
|
const url = new URL(anvilUrl);
|
|
47408
47492
|
const encodedToken = encodeURIComponent(authToken);
|
|
@@ -50117,1224 +50201,1320 @@ var __webpack_exports__ = {};
|
|
|
50117
50201
|
const match = normalizedPath.match(/\/git\/([A-Z0-9]+)\.git(?:$|\/)/);
|
|
50118
50202
|
return match ? match[1] : void 0;
|
|
50119
50203
|
}
|
|
50120
|
-
|
|
50121
|
-
|
|
50122
|
-
|
|
50123
|
-
|
|
50124
|
-
|
|
50125
|
-
|
|
50126
|
-
|
|
50127
|
-
|
|
50128
|
-
|
|
50129
|
-
if (1 === availableUrls.length) return {
|
|
50130
|
-
source: "available-single",
|
|
50131
|
-
url: availableUrls[0]
|
|
50132
|
-
};
|
|
50133
|
-
const fromConfig = getConfig("anvilUrl");
|
|
50134
|
-
if ("string" == typeof fromConfig && fromConfig.trim()) return {
|
|
50135
|
-
source: "config",
|
|
50136
|
-
url: normalizeAnvilUrl(fromConfig.trim())
|
|
50137
|
-
};
|
|
50138
|
-
return {
|
|
50139
|
-
source: "default",
|
|
50140
|
-
url: isDevMode() ? "http://localhost:3000" : "https://anvil.works"
|
|
50141
|
-
};
|
|
50142
|
-
}
|
|
50143
|
-
function decideUsernameForUrl(accounts) {
|
|
50144
|
-
if (0 === accounts.length) return {
|
|
50145
|
-
source: "none"
|
|
50146
|
-
};
|
|
50147
|
-
if (1 === accounts.length) return {
|
|
50148
|
-
source: "single",
|
|
50149
|
-
username: accounts[0]
|
|
50150
|
-
};
|
|
50151
|
-
return {
|
|
50152
|
-
source: "multiple",
|
|
50153
|
-
usernames: [
|
|
50154
|
-
...accounts
|
|
50155
|
-
]
|
|
50156
|
-
};
|
|
50157
|
-
}
|
|
50158
|
-
async function resolveUsernameForUrl(anvilUrl, explicitUsername, promptMessage = "Multiple accounts found. Which account owns this app?") {
|
|
50159
|
-
if (explicitUsername) return explicitUsername;
|
|
50160
|
-
const decision = decideUsernameForUrl(auth_getAccountsForUrl(anvilUrl));
|
|
50161
|
-
if ("none" === decision.source) return;
|
|
50162
|
-
if ("single" === decision.source) {
|
|
50163
|
-
logger_logger.verbose(chalk_source.cyan("Auto-selected account: ") + chalk_source.bold(decision.username));
|
|
50164
|
-
return decision.username;
|
|
50204
|
+
const external_node_url_namespaceObject = require("node:url");
|
|
50205
|
+
var external_node_child_process_ = __webpack_require__("node:child_process");
|
|
50206
|
+
let isDockerCached;
|
|
50207
|
+
function hasDockerEnv() {
|
|
50208
|
+
try {
|
|
50209
|
+
external_node_fs_.statSync('/.dockerenv');
|
|
50210
|
+
return true;
|
|
50211
|
+
} catch {
|
|
50212
|
+
return false;
|
|
50165
50213
|
}
|
|
50166
|
-
const choices = decision.usernames.map((acct)=>({
|
|
50167
|
-
name: acct,
|
|
50168
|
-
value: acct
|
|
50169
|
-
}));
|
|
50170
|
-
choices.push({
|
|
50171
|
-
name: "Cancel",
|
|
50172
|
-
value: null
|
|
50173
|
-
});
|
|
50174
|
-
return logger_logger.select(promptMessage, choices, decision.usernames[0]);
|
|
50175
|
-
}
|
|
50176
|
-
async function confirmReverseLookupWithResolvedUser(anvilUrl, username) {
|
|
50177
|
-
const resolvedUsername = await resolveUsernameForUrl(anvilUrl, username, `Multiple accounts found for ${anvilUrl}. Which account should be used for app lookup?`);
|
|
50178
|
-
if (null === resolvedUsername) return null;
|
|
50179
|
-
const shouldContinue = await logger_logger.confirm(`Search ${anvilUrl} ${resolvedUsername ? `for ${resolvedUsername}` : ""} for matching app IDs? (slower)`, true);
|
|
50180
|
-
return {
|
|
50181
|
-
username: resolvedUsername,
|
|
50182
|
-
shouldContinue
|
|
50183
|
-
};
|
|
50184
|
-
}
|
|
50185
|
-
async function resolveUrlForFallback(explicitUrl) {
|
|
50186
|
-
const decision = decideFallbackUrl(explicitUrl);
|
|
50187
|
-
if ("available-multiple" !== decision.source) return decision.url;
|
|
50188
|
-
const choices = decision.urls.map((url)=>({
|
|
50189
|
-
name: url,
|
|
50190
|
-
value: url
|
|
50191
|
-
}));
|
|
50192
|
-
choices.push({
|
|
50193
|
-
name: "Cancel",
|
|
50194
|
-
value: null
|
|
50195
|
-
});
|
|
50196
|
-
const selectedUrl = await logger_logger.select("Multiple logged-in Anvil URLs found. Which one would you like to use?", choices, decision.urls[0]);
|
|
50197
|
-
return selectedUrl;
|
|
50198
50214
|
}
|
|
50199
|
-
|
|
50200
|
-
if (0 === candidates.length) {
|
|
50201
|
-
logger_logger.warn("Could not auto-detect app ID from repository.");
|
|
50202
|
-
const rl = external_readline_namespaceObject.createInterface({
|
|
50203
|
-
input: process.stdin,
|
|
50204
|
-
output: process.stdout
|
|
50205
|
-
});
|
|
50206
|
-
const manualAppId = await new Promise((resolve)=>{
|
|
50207
|
-
const handleInterrupt = ()=>{
|
|
50208
|
-
rl.close();
|
|
50209
|
-
logger_logger.warn("Operation cancelled by user.");
|
|
50210
|
-
resolve(null);
|
|
50211
|
-
};
|
|
50212
|
-
rl.on("SIGINT", handleInterrupt);
|
|
50213
|
-
rl.question(chalk_source.cyan("Please enter app ID manually (or press Enter to exit): "), (answer)=>{
|
|
50214
|
-
rl.removeListener("SIGINT", handleInterrupt);
|
|
50215
|
-
rl.close();
|
|
50216
|
-
const trimmed = answer.trim();
|
|
50217
|
-
trimmed ? resolve(trimmed) : resolve(null);
|
|
50218
|
-
});
|
|
50219
|
-
});
|
|
50220
|
-
if (manualAppId) return {
|
|
50221
|
-
appId: manualAppId,
|
|
50222
|
-
source: "config",
|
|
50223
|
-
description: "Manual entry"
|
|
50224
|
-
};
|
|
50225
|
-
return null;
|
|
50226
|
-
}
|
|
50227
|
-
const choices = candidates.map((candidate, index)=>({
|
|
50228
|
-
name: formatCandidateLabel(candidate),
|
|
50229
|
-
value: index
|
|
50230
|
-
}));
|
|
50231
|
-
choices.push({
|
|
50232
|
-
name: "Cancel",
|
|
50233
|
-
value: null
|
|
50234
|
-
});
|
|
50215
|
+
function hasDockerCGroup() {
|
|
50235
50216
|
try {
|
|
50236
|
-
|
|
50237
|
-
|
|
50238
|
-
|
|
50239
|
-
type: "list",
|
|
50240
|
-
name: "appId",
|
|
50241
|
-
message: promptText,
|
|
50242
|
-
choices: choices,
|
|
50243
|
-
pageSize: 10
|
|
50244
|
-
}
|
|
50245
|
-
]);
|
|
50246
|
-
if (null === answer.appId) {
|
|
50247
|
-
const rl = external_readline_namespaceObject.createInterface({
|
|
50248
|
-
input: process.stdin,
|
|
50249
|
-
output: process.stdout
|
|
50250
|
-
});
|
|
50251
|
-
const manualAppId = await new Promise((resolve)=>{
|
|
50252
|
-
rl.question(chalk_source.cyan("Please enter app ID manually (or press Enter to exit): "), (answer)=>{
|
|
50253
|
-
rl.close();
|
|
50254
|
-
const trimmed = answer.trim();
|
|
50255
|
-
trimmed ? resolve(trimmed) : resolve(null);
|
|
50256
|
-
});
|
|
50257
|
-
});
|
|
50258
|
-
if (manualAppId) return {
|
|
50259
|
-
appId: manualAppId,
|
|
50260
|
-
source: "config",
|
|
50261
|
-
description: "Manual entry"
|
|
50262
|
-
};
|
|
50263
|
-
return null;
|
|
50264
|
-
}
|
|
50265
|
-
return candidates[answer.appId];
|
|
50266
|
-
} catch (error) {
|
|
50267
|
-
const errorObj = error;
|
|
50268
|
-
if ("ExitPromptError" === errorObj.name || errorObj.message.includes("User force closed")) logger_logger.warn("Operation cancelled by user.");
|
|
50269
|
-
return null;
|
|
50217
|
+
return external_node_fs_.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
|
|
50218
|
+
} catch {
|
|
50219
|
+
return false;
|
|
50270
50220
|
}
|
|
50271
50221
|
}
|
|
50272
|
-
|
|
50222
|
+
function isDocker() {
|
|
50223
|
+
if (void 0 === isDockerCached) isDockerCached = hasDockerEnv() || hasDockerCGroup();
|
|
50224
|
+
return isDockerCached;
|
|
50225
|
+
}
|
|
50226
|
+
let cachedResult;
|
|
50227
|
+
const hasContainerEnv = ()=>{
|
|
50273
50228
|
try {
|
|
50274
|
-
|
|
50275
|
-
const pushUrl = getGitPushUrl(options.appId, authToken, options.anvilUrl);
|
|
50276
|
-
const git = new GitService(options.repoPath);
|
|
50277
|
-
const refSpec = `${options.branchName}:${options.branchName}`;
|
|
50278
|
-
logger_logger.progress("push", "Pushing to Anvil...");
|
|
50279
|
-
await git.push(pushUrl, refSpec, options.force ?? false);
|
|
50280
|
-
logger_logger.progressEnd("push", "Pushed to Anvil");
|
|
50229
|
+
external_node_fs_.statSync('/run/.containerenv');
|
|
50281
50230
|
return true;
|
|
50282
|
-
} catch
|
|
50283
|
-
logger_logger.progressEnd("push", "Push failed");
|
|
50284
|
-
logger_logger.error(`Failed to push: ${errors_getErrorMessage(e)}`);
|
|
50231
|
+
} catch {
|
|
50285
50232
|
return false;
|
|
50286
50233
|
}
|
|
50234
|
+
};
|
|
50235
|
+
function isInsideContainer() {
|
|
50236
|
+
if (void 0 === cachedResult) cachedResult = hasContainerEnv() || isDocker();
|
|
50237
|
+
return cachedResult;
|
|
50287
50238
|
}
|
|
50288
|
-
|
|
50289
|
-
|
|
50290
|
-
|
|
50291
|
-
|
|
50239
|
+
const isWsl = ()=>{
|
|
50240
|
+
if ('linux' !== external_node_process_.platform) return false;
|
|
50241
|
+
if (external_node_os_namespaceObject.release().toLowerCase().includes('microsoft')) {
|
|
50242
|
+
if (isInsideContainer()) return false;
|
|
50243
|
+
return true;
|
|
50244
|
+
}
|
|
50292
50245
|
try {
|
|
50293
|
-
|
|
50294
|
-
|
|
50295
|
-
const hasChanges = await git.hasUncommittedChanges();
|
|
50296
|
-
if (hasChanges) {
|
|
50297
|
-
logger_logger.progress("rebase", "Stashing uncommitted changes...");
|
|
50298
|
-
didStash = await git.stash("anvil-sync: stash before rebase");
|
|
50299
|
-
}
|
|
50300
|
-
logger_logger.progressUpdate("rebase", "Fetching from Anvil...");
|
|
50301
|
-
await git.fetch(fetchUrl, `+${options.branchName}:${tempRef}`);
|
|
50302
|
-
logger_logger.progressUpdate("rebase", "Rebasing...");
|
|
50303
|
-
await git.rebase(tempRef);
|
|
50304
|
-
logger_logger.progressUpdate("rebase", "Pushing rebased changes...");
|
|
50305
|
-
const pushUrl = getGitPushUrl(options.appId, authToken, options.anvilUrl);
|
|
50306
|
-
await git.push(pushUrl, `${options.branchName}:${options.branchName}`, true);
|
|
50307
|
-
logger_logger.progressEnd("rebase", "Rebased and pushed to Anvil");
|
|
50308
|
-
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50309
|
-
if (didStash) try {
|
|
50310
|
-
await git.stashPop();
|
|
50311
|
-
logger_logger.verbose(chalk_source.green("Restored uncommitted changes"));
|
|
50312
|
-
} catch (e) {
|
|
50313
|
-
logger_logger.warn("Uncommitted changes were stashed but could not be restored automatically.");
|
|
50314
|
-
logger_logger.info(chalk_source.gray(" Run: git stash pop"));
|
|
50315
|
-
}
|
|
50316
|
-
return {
|
|
50317
|
-
success: true,
|
|
50318
|
-
conflicted: false
|
|
50319
|
-
};
|
|
50320
|
-
} catch (e) {
|
|
50321
|
-
const msg = errors_getErrorMessage(e);
|
|
50322
|
-
if (msg.includes("rebase") && (msg.includes("conflict") || msg.includes("CONFLICT") || msg.includes("could not apply"))) {
|
|
50323
|
-
try {
|
|
50324
|
-
await git.rebaseAbort();
|
|
50325
|
-
} catch {}
|
|
50326
|
-
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50327
|
-
if (didStash) try {
|
|
50328
|
-
await git.stashPop();
|
|
50329
|
-
} catch {
|
|
50330
|
-
logger_logger.warn("Your uncommitted changes are in the stash. Run: git stash pop");
|
|
50331
|
-
}
|
|
50332
|
-
logger_logger.progressEnd("rebase", "Rebase failed - conflicts");
|
|
50333
|
-
return {
|
|
50334
|
-
success: false,
|
|
50335
|
-
conflicted: true
|
|
50336
|
-
};
|
|
50337
|
-
}
|
|
50338
|
-
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50339
|
-
if (didStash) try {
|
|
50340
|
-
await git.stashPop();
|
|
50341
|
-
} catch {
|
|
50342
|
-
logger_logger.warn("Your uncommitted changes are in the stash. Run: git stash pop");
|
|
50343
|
-
}
|
|
50344
|
-
logger_logger.progressEnd("rebase", "Rebase failed");
|
|
50345
|
-
logger_logger.error(`Failed to rebase: ${msg}`);
|
|
50346
|
-
return {
|
|
50347
|
-
success: false,
|
|
50348
|
-
conflicted: false
|
|
50349
|
-
};
|
|
50350
|
-
}
|
|
50351
|
-
}
|
|
50352
|
-
async function fetchAndHardResetFromAnvil(options) {
|
|
50353
|
-
const git = new GitService(options.repoPath);
|
|
50354
|
-
const tempRef = `anvil-reset-temp-${Date.now()}`;
|
|
50355
|
-
try {
|
|
50356
|
-
const authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
50357
|
-
const fetchUrl = getGitFetchUrl(options.appId, authToken, options.anvilUrl);
|
|
50358
|
-
logger_logger.progress("reset", "Fetching from Anvil...");
|
|
50359
|
-
await git.fetch(fetchUrl, `+${options.branchName}:${tempRef}`);
|
|
50360
|
-
logger_logger.progressUpdate("reset", "Resetting to Anvil's version...");
|
|
50361
|
-
await git.reset(tempRef, "hard");
|
|
50362
|
-
logger_logger.progressEnd("reset", "Reset to Anvil's version");
|
|
50363
|
-
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50364
|
-
return true;
|
|
50365
|
-
} catch (e) {
|
|
50366
|
-
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50367
|
-
logger_logger.progressEnd("reset", "Reset failed");
|
|
50368
|
-
logger_logger.error(`Failed to reset: ${errors_getErrorMessage(e)}`);
|
|
50246
|
+
return external_node_fs_.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') ? !isInsideContainer() : false;
|
|
50247
|
+
} catch {
|
|
50369
50248
|
return false;
|
|
50370
50249
|
}
|
|
50250
|
+
};
|
|
50251
|
+
const is_wsl = external_node_process_.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
50252
|
+
const wslDrivesMountPoint = (()=>{
|
|
50253
|
+
const defaultMountPoint = '/mnt/';
|
|
50254
|
+
let mountPoint;
|
|
50255
|
+
return async function() {
|
|
50256
|
+
if (mountPoint) return mountPoint;
|
|
50257
|
+
const configFilePath = '/etc/wsl.conf';
|
|
50258
|
+
let isConfigFileExists = false;
|
|
50259
|
+
try {
|
|
50260
|
+
await external_node_fs_promises_namespaceObject.access(configFilePath, external_node_fs_promises_namespaceObject.constants.F_OK);
|
|
50261
|
+
isConfigFileExists = true;
|
|
50262
|
+
} catch {}
|
|
50263
|
+
if (!isConfigFileExists) return defaultMountPoint;
|
|
50264
|
+
const configContent = await external_node_fs_promises_namespaceObject.readFile(configFilePath, {
|
|
50265
|
+
encoding: 'utf8'
|
|
50266
|
+
});
|
|
50267
|
+
const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
|
|
50268
|
+
if (!configMountPoint) return defaultMountPoint;
|
|
50269
|
+
mountPoint = configMountPoint.groups.mountPoint.trim();
|
|
50270
|
+
mountPoint = mountPoint.endsWith('/') ? mountPoint : `${mountPoint}/`;
|
|
50271
|
+
return mountPoint;
|
|
50272
|
+
};
|
|
50273
|
+
})();
|
|
50274
|
+
const powerShellPathFromWsl = async ()=>{
|
|
50275
|
+
const mountPoint = await wslDrivesMountPoint();
|
|
50276
|
+
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
|
|
50277
|
+
};
|
|
50278
|
+
const powerShellPath = async ()=>{
|
|
50279
|
+
if (is_wsl) return powerShellPathFromWsl();
|
|
50280
|
+
return `${external_node_process_.env.SYSTEMROOT || external_node_process_.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
50281
|
+
};
|
|
50282
|
+
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
50283
|
+
const define = (value)=>Object.defineProperty(object, propertyName, {
|
|
50284
|
+
value,
|
|
50285
|
+
enumerable: true,
|
|
50286
|
+
writable: true
|
|
50287
|
+
});
|
|
50288
|
+
Object.defineProperty(object, propertyName, {
|
|
50289
|
+
configurable: true,
|
|
50290
|
+
enumerable: true,
|
|
50291
|
+
get () {
|
|
50292
|
+
const result = valueGetter();
|
|
50293
|
+
define(result);
|
|
50294
|
+
return result;
|
|
50295
|
+
},
|
|
50296
|
+
set (value) {
|
|
50297
|
+
define(value);
|
|
50298
|
+
}
|
|
50299
|
+
});
|
|
50300
|
+
return object;
|
|
50371
50301
|
}
|
|
50372
|
-
|
|
50373
|
-
|
|
50374
|
-
if (
|
|
50375
|
-
|
|
50376
|
-
|
|
50377
|
-
|
|
50378
|
-
|
|
50302
|
+
const execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_.execFile);
|
|
50303
|
+
async function defaultBrowserId() {
|
|
50304
|
+
if ('darwin' !== external_node_process_.platform) throw new Error('macOS only');
|
|
50305
|
+
const { stdout } = await execFileAsync('defaults', [
|
|
50306
|
+
'read',
|
|
50307
|
+
'com.apple.LaunchServices/com.apple.launchservices.secure',
|
|
50308
|
+
'LSHandlers'
|
|
50309
|
+
]);
|
|
50310
|
+
const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
50311
|
+
const browserId = match?.groups.id ?? 'com.apple.Safari';
|
|
50312
|
+
if ('com.apple.safari' === browserId) return 'com.apple.Safari';
|
|
50313
|
+
return browserId;
|
|
50379
50314
|
}
|
|
50380
|
-
|
|
50381
|
-
|
|
50382
|
-
|
|
50383
|
-
|
|
50384
|
-
|
|
50385
|
-
|
|
50386
|
-
|
|
50387
|
-
|
|
50388
|
-
|
|
50389
|
-
|
|
50390
|
-
|
|
50391
|
-
|
|
50392
|
-
|
|
50393
|
-
|
|
50394
|
-
logger_logger.progressEnd("verify");
|
|
50395
|
-
logger_logger.verbose(chalk_source.gray(`Could not re-verify status: ${errors_getErrorMessage(e)}`));
|
|
50396
|
-
return null;
|
|
50397
|
-
}
|
|
50315
|
+
const run_applescript_execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_.execFile);
|
|
50316
|
+
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
50317
|
+
if ('darwin' !== external_node_process_.platform) throw new Error('macOS only');
|
|
50318
|
+
const outputArguments = humanReadableOutput ? [] : [
|
|
50319
|
+
'-ss'
|
|
50320
|
+
];
|
|
50321
|
+
const execOptions = {};
|
|
50322
|
+
if (signal) execOptions.signal = signal;
|
|
50323
|
+
const { stdout } = await run_applescript_execFileAsync("osascript", [
|
|
50324
|
+
'-e',
|
|
50325
|
+
script,
|
|
50326
|
+
outputArguments
|
|
50327
|
+
], execOptions);
|
|
50328
|
+
return stdout.trim();
|
|
50398
50329
|
}
|
|
50399
|
-
async function
|
|
50400
|
-
|
|
50401
|
-
|
|
50402
|
-
|
|
50403
|
-
|
|
50404
|
-
|
|
50405
|
-
|
|
50406
|
-
|
|
50407
|
-
|
|
50408
|
-
|
|
50330
|
+
async function bundleName(bundleId) {
|
|
50331
|
+
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string\ntell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
50332
|
+
}
|
|
50333
|
+
const windows_execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_.execFile);
|
|
50334
|
+
const windowsBrowserProgIds = {
|
|
50335
|
+
MSEdgeHTM: {
|
|
50336
|
+
name: 'Edge',
|
|
50337
|
+
id: 'com.microsoft.edge'
|
|
50338
|
+
},
|
|
50339
|
+
MSEdgeBHTML: {
|
|
50340
|
+
name: 'Edge Beta',
|
|
50341
|
+
id: 'com.microsoft.edge.beta'
|
|
50342
|
+
},
|
|
50343
|
+
MSEdgeDHTML: {
|
|
50344
|
+
name: 'Edge Dev',
|
|
50345
|
+
id: 'com.microsoft.edge.dev'
|
|
50346
|
+
},
|
|
50347
|
+
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: {
|
|
50348
|
+
name: 'Edge',
|
|
50349
|
+
id: 'com.microsoft.edge.old'
|
|
50350
|
+
},
|
|
50351
|
+
ChromeHTML: {
|
|
50352
|
+
name: 'Chrome',
|
|
50353
|
+
id: 'com.google.chrome'
|
|
50354
|
+
},
|
|
50355
|
+
ChromeBHTML: {
|
|
50356
|
+
name: 'Chrome Beta',
|
|
50357
|
+
id: 'com.google.chrome.beta'
|
|
50358
|
+
},
|
|
50359
|
+
ChromeDHTML: {
|
|
50360
|
+
name: 'Chrome Dev',
|
|
50361
|
+
id: 'com.google.chrome.dev'
|
|
50362
|
+
},
|
|
50363
|
+
ChromiumHTM: {
|
|
50364
|
+
name: 'Chromium',
|
|
50365
|
+
id: 'org.chromium.Chromium'
|
|
50366
|
+
},
|
|
50367
|
+
BraveHTML: {
|
|
50368
|
+
name: 'Brave',
|
|
50369
|
+
id: 'com.brave.Browser'
|
|
50370
|
+
},
|
|
50371
|
+
BraveBHTML: {
|
|
50372
|
+
name: 'Brave Beta',
|
|
50373
|
+
id: 'com.brave.Browser.beta'
|
|
50374
|
+
},
|
|
50375
|
+
BraveDHTML: {
|
|
50376
|
+
name: 'Brave Dev',
|
|
50377
|
+
id: 'com.brave.Browser.dev'
|
|
50378
|
+
},
|
|
50379
|
+
BraveSSHTM: {
|
|
50380
|
+
name: 'Brave Nightly',
|
|
50381
|
+
id: 'com.brave.Browser.nightly'
|
|
50382
|
+
},
|
|
50383
|
+
FirefoxURL: {
|
|
50384
|
+
name: 'Firefox',
|
|
50385
|
+
id: 'org.mozilla.firefox'
|
|
50386
|
+
},
|
|
50387
|
+
OperaStable: {
|
|
50388
|
+
name: 'Opera',
|
|
50389
|
+
id: 'com.operasoftware.Opera'
|
|
50390
|
+
},
|
|
50391
|
+
VivaldiHTM: {
|
|
50392
|
+
name: 'Vivaldi',
|
|
50393
|
+
id: 'com.vivaldi.Vivaldi'
|
|
50394
|
+
},
|
|
50395
|
+
'IE.HTTP': {
|
|
50396
|
+
name: 'Internet Explorer',
|
|
50397
|
+
id: 'com.microsoft.ie'
|
|
50409
50398
|
}
|
|
50399
|
+
};
|
|
50400
|
+
new Map(Object.entries(windowsBrowserProgIds));
|
|
50401
|
+
class UnknownBrowserError extends Error {
|
|
50410
50402
|
}
|
|
50411
|
-
async function
|
|
50412
|
-
const
|
|
50413
|
-
|
|
50414
|
-
|
|
50415
|
-
|
|
50416
|
-
|
|
50417
|
-
|
|
50418
|
-
|
|
50419
|
-
|
|
50420
|
-
|
|
50421
|
-
|
|
50422
|
-
|
|
50423
|
-
|
|
50424
|
-
|
|
50425
|
-
|
|
50426
|
-
|
|
50427
|
-
|
|
50428
|
-
|
|
50429
|
-
|
|
50430
|
-
|
|
50431
|
-
|
|
50432
|
-
|
|
50433
|
-
|
|
50434
|
-
|
|
50435
|
-
repoPath: options.repoPath,
|
|
50436
|
-
appId: options.appId,
|
|
50437
|
-
anvilUrl: options.anvilUrl,
|
|
50438
|
-
branchName,
|
|
50439
|
-
username: options.username
|
|
50440
|
-
});
|
|
50441
|
-
if (!pushed) return false;
|
|
50442
|
-
return await recreateSessionAndValidate(options);
|
|
50403
|
+
async function defaultBrowser(_execFileAsync = windows_execFileAsync) {
|
|
50404
|
+
const { stdout } = await _execFileAsync('reg', [
|
|
50405
|
+
'QUERY',
|
|
50406
|
+
' HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice',
|
|
50407
|
+
'/v',
|
|
50408
|
+
'ProgId'
|
|
50409
|
+
]);
|
|
50410
|
+
const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
|
|
50411
|
+
if (!match) throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
|
|
50412
|
+
const { id } = match.groups;
|
|
50413
|
+
const browser = windowsBrowserProgIds[id];
|
|
50414
|
+
if (!browser) throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
|
|
50415
|
+
return browser;
|
|
50416
|
+
}
|
|
50417
|
+
const default_browser_execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_.execFile);
|
|
50418
|
+
const titleize = (string)=>string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x)=>x.toUpperCase());
|
|
50419
|
+
async function default_browser_defaultBrowser() {
|
|
50420
|
+
if ('darwin' === external_node_process_.platform) {
|
|
50421
|
+
const id = await defaultBrowserId();
|
|
50422
|
+
const name = await bundleName(id);
|
|
50423
|
+
return {
|
|
50424
|
+
name,
|
|
50425
|
+
id
|
|
50426
|
+
};
|
|
50443
50427
|
}
|
|
50444
|
-
if (
|
|
50445
|
-
|
|
50446
|
-
|
|
50447
|
-
|
|
50448
|
-
|
|
50449
|
-
|
|
50450
|
-
|
|
50451
|
-
|
|
50452
|
-
|
|
50453
|
-
|
|
50454
|
-
|
|
50455
|
-
|
|
50456
|
-
|
|
50457
|
-
|
|
50458
|
-
|
|
50459
|
-
|
|
50460
|
-
|
|
50461
|
-
|
|
50462
|
-
|
|
50463
|
-
|
|
50428
|
+
if ('linux' === external_node_process_.platform) {
|
|
50429
|
+
const { stdout } = await default_browser_execFileAsync('xdg-mime', [
|
|
50430
|
+
'query',
|
|
50431
|
+
'default',
|
|
50432
|
+
'x-scheme-handler/http'
|
|
50433
|
+
]);
|
|
50434
|
+
const id = stdout.trim();
|
|
50435
|
+
const name = titleize(id.replace(/.desktop$/, '').replace('-', ' '));
|
|
50436
|
+
return {
|
|
50437
|
+
name,
|
|
50438
|
+
id
|
|
50439
|
+
};
|
|
50440
|
+
}
|
|
50441
|
+
if ('win32' === external_node_process_.platform) return defaultBrowser();
|
|
50442
|
+
throw new Error('Only macOS, Linux, and Windows are supported');
|
|
50443
|
+
}
|
|
50444
|
+
const execFile = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_.execFile);
|
|
50445
|
+
const open_dirname = external_node_path_.dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
|
|
50446
|
+
const localXdgOpenPath = external_node_path_.join(open_dirname, 'xdg-open');
|
|
50447
|
+
const { platform, arch } = external_node_process_;
|
|
50448
|
+
async function getWindowsDefaultBrowserFromWsl() {
|
|
50449
|
+
const powershellPath = await powerShellPath();
|
|
50450
|
+
const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
50451
|
+
const encodedCommand = external_node_buffer_namespaceObject.Buffer.from(rawCommand, 'utf16le').toString('base64');
|
|
50452
|
+
const { stdout } = await execFile(powershellPath, [
|
|
50453
|
+
'-NoProfile',
|
|
50454
|
+
'-NonInteractive',
|
|
50455
|
+
'-ExecutionPolicy',
|
|
50456
|
+
'Bypass',
|
|
50457
|
+
'-EncodedCommand',
|
|
50458
|
+
encodedCommand
|
|
50459
|
+
], {
|
|
50460
|
+
encoding: 'utf8'
|
|
50461
|
+
});
|
|
50462
|
+
const progId = stdout.trim();
|
|
50463
|
+
const browserMap = {
|
|
50464
|
+
ChromeHTML: 'com.google.chrome',
|
|
50465
|
+
BraveHTML: 'com.brave.Browser',
|
|
50466
|
+
MSEdgeHTM: 'com.microsoft.edge',
|
|
50467
|
+
FirefoxURL: 'org.mozilla.firefox'
|
|
50468
|
+
};
|
|
50469
|
+
return browserMap[progId] ? {
|
|
50470
|
+
id: browserMap[progId]
|
|
50471
|
+
} : {};
|
|
50472
|
+
}
|
|
50473
|
+
const pTryEach = async (array, mapper)=>{
|
|
50474
|
+
let latestError;
|
|
50475
|
+
for (const item of array)try {
|
|
50476
|
+
return await mapper(item);
|
|
50477
|
+
} catch (error) {
|
|
50478
|
+
latestError = error;
|
|
50479
|
+
}
|
|
50480
|
+
throw latestError;
|
|
50481
|
+
};
|
|
50482
|
+
const baseOpen = async (options)=>{
|
|
50483
|
+
options = {
|
|
50484
|
+
wait: false,
|
|
50485
|
+
background: false,
|
|
50486
|
+
newInstance: false,
|
|
50487
|
+
allowNonzeroExitCode: false,
|
|
50488
|
+
...options
|
|
50489
|
+
};
|
|
50490
|
+
if (Array.isArray(options.app)) return pTryEach(options.app, (singleApp)=>baseOpen({
|
|
50491
|
+
...options,
|
|
50492
|
+
app: singleApp
|
|
50493
|
+
}));
|
|
50494
|
+
let { name: app, arguments: appArguments = [] } = options.app ?? {};
|
|
50495
|
+
appArguments = [
|
|
50496
|
+
...appArguments
|
|
50497
|
+
];
|
|
50498
|
+
if (Array.isArray(app)) return pTryEach(app, (appName)=>baseOpen({
|
|
50499
|
+
...options,
|
|
50500
|
+
app: {
|
|
50501
|
+
name: appName,
|
|
50502
|
+
arguments: appArguments
|
|
50464
50503
|
}
|
|
50465
|
-
}
|
|
50466
|
-
|
|
50467
|
-
|
|
50468
|
-
|
|
50469
|
-
|
|
50470
|
-
|
|
50471
|
-
|
|
50472
|
-
|
|
50473
|
-
|
|
50474
|
-
|
|
50475
|
-
|
|
50476
|
-
|
|
50477
|
-
|
|
50478
|
-
|
|
50479
|
-
|
|
50480
|
-
|
|
50481
|
-
|
|
50482
|
-
|
|
50483
|
-
|
|
50484
|
-
|
|
50485
|
-
|
|
50486
|
-
|
|
50487
|
-
|
|
50488
|
-
|
|
50489
|
-
|
|
50490
|
-
|
|
50491
|
-
|
|
50492
|
-
|
|
50493
|
-
|
|
50504
|
+
}));
|
|
50505
|
+
if ('browser' === app || 'browserPrivate' === app) {
|
|
50506
|
+
const ids = {
|
|
50507
|
+
'com.google.chrome': 'chrome',
|
|
50508
|
+
'google-chrome.desktop': 'chrome',
|
|
50509
|
+
'com.brave.Browser': 'brave',
|
|
50510
|
+
'org.mozilla.firefox': 'firefox',
|
|
50511
|
+
'firefox.desktop': 'firefox',
|
|
50512
|
+
'com.microsoft.msedge': 'edge',
|
|
50513
|
+
'com.microsoft.edge': 'edge',
|
|
50514
|
+
'com.microsoft.edgemac': 'edge',
|
|
50515
|
+
'microsoft-edge.desktop': 'edge'
|
|
50516
|
+
};
|
|
50517
|
+
const flags = {
|
|
50518
|
+
chrome: '--incognito',
|
|
50519
|
+
brave: '--incognito',
|
|
50520
|
+
firefox: '--private-window',
|
|
50521
|
+
edge: '--inPrivate'
|
|
50522
|
+
};
|
|
50523
|
+
const browser = is_wsl ? await getWindowsDefaultBrowserFromWsl() : await default_browser_defaultBrowser();
|
|
50524
|
+
if (browser.id in ids) {
|
|
50525
|
+
const browserName = ids[browser.id];
|
|
50526
|
+
if ('browserPrivate' === app) appArguments.push(flags[browserName]);
|
|
50527
|
+
return baseOpen({
|
|
50528
|
+
...options,
|
|
50529
|
+
app: {
|
|
50530
|
+
name: open_apps[browserName],
|
|
50531
|
+
arguments: appArguments
|
|
50532
|
+
}
|
|
50494
50533
|
});
|
|
50495
|
-
if (result.conflicted) {
|
|
50496
|
-
logger_logger.error("Rebase failed due to conflicts. Please resolve manually:");
|
|
50497
|
-
logger_logger.info(chalk_source.gray(" 1. Run: git fetch anvil && git rebase anvil/" + branchName));
|
|
50498
|
-
logger_logger.info(chalk_source.gray(" 2. Resolve conflicts, then: git rebase --continue"));
|
|
50499
|
-
logger_logger.info(chalk_source.gray(" 3. Push: git push anvil " + branchName));
|
|
50500
|
-
return false;
|
|
50501
|
-
}
|
|
50502
|
-
if (!result.success) return false;
|
|
50503
|
-
return await recreateSessionAndValidate(options);
|
|
50504
50534
|
}
|
|
50505
|
-
|
|
50506
|
-
|
|
50507
|
-
|
|
50508
|
-
|
|
50509
|
-
|
|
50510
|
-
|
|
50511
|
-
|
|
50512
|
-
|
|
50513
|
-
|
|
50514
|
-
|
|
50515
|
-
|
|
50516
|
-
|
|
50517
|
-
|
|
50518
|
-
|
|
50519
|
-
|
|
50520
|
-
|
|
50521
|
-
|
|
50522
|
-
|
|
50523
|
-
|
|
50524
|
-
|
|
50525
|
-
|
|
50535
|
+
throw new Error(`${browser.name} is not supported as a default browser`);
|
|
50536
|
+
}
|
|
50537
|
+
let command;
|
|
50538
|
+
const cliArguments = [];
|
|
50539
|
+
const childProcessOptions = {};
|
|
50540
|
+
if ('darwin' === platform) {
|
|
50541
|
+
command = 'open';
|
|
50542
|
+
if (options.wait) cliArguments.push('--wait-apps');
|
|
50543
|
+
if (options.background) cliArguments.push('--background');
|
|
50544
|
+
if (options.newInstance) cliArguments.push('--new');
|
|
50545
|
+
if (app) cliArguments.push('-a', app);
|
|
50546
|
+
} else if ('win32' !== platform && (!is_wsl || isInsideContainer() || app)) {
|
|
50547
|
+
if (app) command = app;
|
|
50548
|
+
else {
|
|
50549
|
+
const isBundled = !open_dirname || '/' === open_dirname;
|
|
50550
|
+
let exeLocalXdgOpen = false;
|
|
50551
|
+
try {
|
|
50552
|
+
await external_node_fs_promises_namespaceObject.access(localXdgOpenPath, external_node_fs_promises_namespaceObject.constants.X_OK);
|
|
50553
|
+
exeLocalXdgOpen = true;
|
|
50554
|
+
} catch {}
|
|
50555
|
+
const useSystemXdgOpen = external_node_process_.versions.electron ?? ('android' === platform || isBundled || !exeLocalXdgOpen);
|
|
50556
|
+
command = useSystemXdgOpen ? 'xdg-open' : localXdgOpenPath;
|
|
50526
50557
|
}
|
|
50527
|
-
|
|
50528
|
-
if (
|
|
50529
|
-
|
|
50530
|
-
|
|
50531
|
-
repoPath: options.repoPath,
|
|
50532
|
-
appId: options.appId,
|
|
50533
|
-
anvilUrl: options.anvilUrl,
|
|
50534
|
-
branchName,
|
|
50535
|
-
username: options.username
|
|
50536
|
-
});
|
|
50537
|
-
if (result.conflicted) {
|
|
50538
|
-
logger_logger.error("Rebase failed due to conflicts. Please resolve manually:");
|
|
50539
|
-
logger_logger.info(chalk_source.gray(" 1. Run: git fetch anvil && git rebase anvil/" + branchName));
|
|
50540
|
-
logger_logger.info(chalk_source.gray(" 2. Resolve conflicts, then: git rebase --continue"));
|
|
50541
|
-
logger_logger.info(chalk_source.gray(" 3. Push: git push anvil " + branchName));
|
|
50542
|
-
return false;
|
|
50543
|
-
}
|
|
50544
|
-
if (!result.success) return false;
|
|
50545
|
-
return await recreateSessionAndValidate(options);
|
|
50546
|
-
}
|
|
50547
|
-
if ("reset" === action) {
|
|
50548
|
-
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?`;
|
|
50549
|
-
const confirmed = await logger_logger.confirm(resetWarning, false);
|
|
50550
|
-
if (!confirmed) {
|
|
50551
|
-
logger_logger.warn("Watch cancelled.");
|
|
50552
|
-
return false;
|
|
50553
|
-
}
|
|
50554
|
-
const reset = await fetchAndHardResetFromAnvil({
|
|
50555
|
-
repoPath: options.repoPath,
|
|
50556
|
-
appId: options.appId,
|
|
50557
|
-
anvilUrl: options.anvilUrl,
|
|
50558
|
-
branchName,
|
|
50559
|
-
username: options.username
|
|
50560
|
-
});
|
|
50561
|
-
if (!reset) return false;
|
|
50562
|
-
return await recreateSessionAndValidate(options);
|
|
50563
|
-
}
|
|
50564
|
-
if ("push" === action) {
|
|
50565
|
-
const confirmed = await logger_logger.confirm("This will overwrite Anvil's version. Are you sure?", false);
|
|
50566
|
-
if (!confirmed) {
|
|
50567
|
-
logger_logger.warn("Watch cancelled.");
|
|
50568
|
-
return false;
|
|
50569
|
-
}
|
|
50570
|
-
const pushed = await pushToAnvil({
|
|
50571
|
-
repoPath: options.repoPath,
|
|
50572
|
-
appId: options.appId,
|
|
50573
|
-
anvilUrl: options.anvilUrl,
|
|
50574
|
-
branchName,
|
|
50575
|
-
username: options.username,
|
|
50576
|
-
force: true
|
|
50577
|
-
});
|
|
50578
|
-
if (!pushed) return false;
|
|
50579
|
-
return await recreateSessionAndValidate(options);
|
|
50558
|
+
if (appArguments.length > 0) cliArguments.push(...appArguments);
|
|
50559
|
+
if (!options.wait) {
|
|
50560
|
+
childProcessOptions.stdio = 'ignore';
|
|
50561
|
+
childProcessOptions.detached = true;
|
|
50580
50562
|
}
|
|
50581
50563
|
} else {
|
|
50582
|
-
|
|
50583
|
-
|
|
50584
|
-
if (
|
|
50585
|
-
|
|
50586
|
-
|
|
50587
|
-
|
|
50588
|
-
|
|
50589
|
-
|
|
50590
|
-
|
|
50591
|
-
|
|
50592
|
-
|
|
50593
|
-
|
|
50594
|
-
|
|
50595
|
-
|
|
50596
|
-
session.cleanup();
|
|
50597
|
-
return false;
|
|
50564
|
+
command = await powerShellPath();
|
|
50565
|
+
cliArguments.push('-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-EncodedCommand');
|
|
50566
|
+
if (!is_wsl) childProcessOptions.windowsVerbatimArguments = true;
|
|
50567
|
+
const encodedArguments = [
|
|
50568
|
+
'Start'
|
|
50569
|
+
];
|
|
50570
|
+
if (options.wait) encodedArguments.push('-Wait');
|
|
50571
|
+
if (app) {
|
|
50572
|
+
encodedArguments.push(`"\`"${app}\`""`);
|
|
50573
|
+
if (options.target) appArguments.push(options.target);
|
|
50574
|
+
} else if (options.target) encodedArguments.push(`"${options.target}"`);
|
|
50575
|
+
if (appArguments.length > 0) {
|
|
50576
|
+
appArguments = appArguments.map((argument)=>`"\`"${argument}\`""`);
|
|
50577
|
+
encodedArguments.push('-ArgumentList', appArguments.join(','));
|
|
50598
50578
|
}
|
|
50599
|
-
|
|
50600
|
-
|
|
50601
|
-
|
|
50602
|
-
|
|
50603
|
-
|
|
50604
|
-
|
|
50605
|
-
|
|
50579
|
+
options.target = external_node_buffer_namespaceObject.Buffer.from(encodedArguments.join(' '), 'utf16le').toString('base64');
|
|
50580
|
+
}
|
|
50581
|
+
if ('darwin' === platform && appArguments.length > 0) cliArguments.push('--args', ...appArguments);
|
|
50582
|
+
if (options.target) cliArguments.push(options.target);
|
|
50583
|
+
const subprocess = external_node_child_process_.spawn(command, cliArguments, childProcessOptions);
|
|
50584
|
+
if (options.wait) return new Promise((resolve, reject)=>{
|
|
50585
|
+
subprocess.once('error', reject);
|
|
50586
|
+
subprocess.once('close', (exitCode)=>{
|
|
50587
|
+
if (!options.allowNonzeroExitCode && exitCode > 0) return void reject(new Error(`Exited with code ${exitCode}`));
|
|
50588
|
+
resolve(subprocess);
|
|
50589
|
+
});
|
|
50590
|
+
});
|
|
50591
|
+
subprocess.unref();
|
|
50592
|
+
return subprocess;
|
|
50593
|
+
};
|
|
50594
|
+
const open_open = (target, options)=>{
|
|
50595
|
+
if ('string' != typeof target) throw new TypeError('Expected a `target`');
|
|
50596
|
+
return baseOpen({
|
|
50597
|
+
...options,
|
|
50598
|
+
target
|
|
50599
|
+
});
|
|
50600
|
+
};
|
|
50601
|
+
function detectArchBinary(binary) {
|
|
50602
|
+
if ('string' == typeof binary || Array.isArray(binary)) return binary;
|
|
50603
|
+
const { [arch]: archBinary } = binary;
|
|
50604
|
+
if (!archBinary) throw new Error(`${arch} is not supported`);
|
|
50605
|
+
return archBinary;
|
|
50606
|
+
}
|
|
50607
|
+
function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
|
|
50608
|
+
if (wsl && is_wsl) return detectArchBinary(wsl);
|
|
50609
|
+
if (!platformBinary) throw new Error(`${platform} is not supported`);
|
|
50610
|
+
return detectArchBinary(platformBinary);
|
|
50611
|
+
}
|
|
50612
|
+
const open_apps = {};
|
|
50613
|
+
defineLazyProperty(open_apps, 'chrome', ()=>detectPlatformBinary({
|
|
50614
|
+
darwin: 'google chrome',
|
|
50615
|
+
win32: 'chrome',
|
|
50616
|
+
linux: [
|
|
50617
|
+
'google-chrome',
|
|
50618
|
+
'google-chrome-stable',
|
|
50619
|
+
'chromium'
|
|
50620
|
+
]
|
|
50621
|
+
}, {
|
|
50622
|
+
wsl: {
|
|
50623
|
+
ia32: '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe',
|
|
50624
|
+
x64: [
|
|
50625
|
+
'/mnt/c/Program Files/Google/Chrome/Application/chrome.exe',
|
|
50626
|
+
'/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'
|
|
50627
|
+
]
|
|
50606
50628
|
}
|
|
50607
|
-
|
|
50608
|
-
|
|
50609
|
-
|
|
50610
|
-
|
|
50611
|
-
|
|
50612
|
-
|
|
50613
|
-
|
|
50614
|
-
|
|
50629
|
+
}));
|
|
50630
|
+
defineLazyProperty(open_apps, 'brave', ()=>detectPlatformBinary({
|
|
50631
|
+
darwin: 'brave browser',
|
|
50632
|
+
win32: 'brave',
|
|
50633
|
+
linux: [
|
|
50634
|
+
'brave-browser',
|
|
50635
|
+
'brave'
|
|
50636
|
+
]
|
|
50637
|
+
}, {
|
|
50638
|
+
wsl: {
|
|
50639
|
+
ia32: '/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe',
|
|
50640
|
+
x64: [
|
|
50641
|
+
'/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe',
|
|
50642
|
+
'/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe'
|
|
50643
|
+
]
|
|
50615
50644
|
}
|
|
50616
|
-
|
|
50645
|
+
}));
|
|
50646
|
+
defineLazyProperty(open_apps, 'firefox', ()=>detectPlatformBinary({
|
|
50647
|
+
darwin: 'firefox',
|
|
50648
|
+
win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
|
|
50649
|
+
linux: 'firefox'
|
|
50650
|
+
}, {
|
|
50651
|
+
wsl: '/mnt/c/Program Files/Mozilla Firefox/firefox.exe'
|
|
50652
|
+
}));
|
|
50653
|
+
defineLazyProperty(open_apps, 'edge', ()=>detectPlatformBinary({
|
|
50654
|
+
darwin: 'microsoft edge',
|
|
50655
|
+
win32: 'msedge',
|
|
50656
|
+
linux: [
|
|
50657
|
+
'microsoft-edge',
|
|
50658
|
+
'microsoft-edge-dev'
|
|
50659
|
+
]
|
|
50660
|
+
}, {
|
|
50661
|
+
wsl: '/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'
|
|
50662
|
+
}));
|
|
50663
|
+
defineLazyProperty(open_apps, 'browser', ()=>'browser');
|
|
50664
|
+
defineLazyProperty(open_apps, 'browserPrivate', ()=>'browserPrivate');
|
|
50665
|
+
const node_modules_open = open_open;
|
|
50666
|
+
const defaultDeps = {
|
|
50667
|
+
openSystem: async (pathToOpen)=>node_modules_open(pathToOpen),
|
|
50668
|
+
isCommandAvailable: isCommandAvailable,
|
|
50669
|
+
spawnShellCommand: async (commandLine)=>{
|
|
50670
|
+
await new Promise((resolve, reject)=>{
|
|
50671
|
+
const child = (0, external_child_process_.spawn)(commandLine, {
|
|
50672
|
+
shell: true,
|
|
50673
|
+
stdio: "inherit"
|
|
50674
|
+
});
|
|
50675
|
+
child.on("error", reject);
|
|
50676
|
+
child.on("exit", (code)=>{
|
|
50677
|
+
if (0 === code || null === code) resolve();
|
|
50678
|
+
else reject(new Error(`Editor command exited with code ${code}`));
|
|
50679
|
+
});
|
|
50680
|
+
});
|
|
50617
50681
|
}
|
|
50618
|
-
|
|
50619
|
-
|
|
50620
|
-
|
|
50621
|
-
|
|
50622
|
-
const
|
|
50623
|
-
|
|
50624
|
-
|
|
50625
|
-
|
|
50626
|
-
|
|
50627
|
-
|
|
50628
|
-
|
|
50629
|
-
|
|
50630
|
-
|
|
50631
|
-
|
|
50632
|
-
])).trim();
|
|
50633
|
-
if (actualBranch !== newBranch) logger_logger.verbose(chalk_source.yellow(`Branch changed again to ${chalk_source.bold(actualBranch)}, using that instead`));
|
|
50634
|
-
logger_logger.progress("init", "Initializing watch session...");
|
|
50635
|
-
try {
|
|
50636
|
-
const newSession = await api_watch(repoPath, appId, anvilUrl, stagedOnly, options.username);
|
|
50637
|
-
logger_logger.progressEnd("init");
|
|
50638
|
-
const started = await checkSyncStatusAndStart(newSession, options);
|
|
50639
|
-
if (!started) process.exit(0);
|
|
50640
|
-
} catch (e) {
|
|
50641
|
-
logger_logger.progressEnd("init", "Failed");
|
|
50642
|
-
logger_logger.error("Failed to restart watch: " + errors_getErrorMessage(e));
|
|
50643
|
-
process.exit(1);
|
|
50644
|
-
}
|
|
50645
|
-
} catch (error) {
|
|
50646
|
-
logger_logger.error(`Error handling branch change: ${error.message}`);
|
|
50647
|
-
process.exit(1);
|
|
50682
|
+
};
|
|
50683
|
+
function parseCommandTokens(command) {
|
|
50684
|
+
const input = command.trim();
|
|
50685
|
+
if (!input) return [];
|
|
50686
|
+
const tokens = [];
|
|
50687
|
+
let current = "";
|
|
50688
|
+
let quote = null;
|
|
50689
|
+
let escaping = false;
|
|
50690
|
+
for(let i = 0; i < input.length; i += 1){
|
|
50691
|
+
const ch = input[i];
|
|
50692
|
+
if (escaping) {
|
|
50693
|
+
current += ch;
|
|
50694
|
+
escaping = false;
|
|
50695
|
+
continue;
|
|
50648
50696
|
}
|
|
50649
|
-
|
|
50650
|
-
|
|
50651
|
-
|
|
50652
|
-
logger_logger.verbose(chalk_source.yellow(` Current branch: ${currentBranch}`));
|
|
50653
|
-
logger_logger.verbose(chalk_source.yellow(" Please restart anvil to re-validate the branch."));
|
|
50654
|
-
session.cleanup();
|
|
50655
|
-
process.exit(1);
|
|
50656
|
-
});
|
|
50657
|
-
session.on("max-retries-exceeded", async ()=>{
|
|
50658
|
-
if (autoMode) {
|
|
50659
|
-
logger_logger.info(chalk_source.cyan("→ Auto-restarting watch session..."));
|
|
50660
|
-
session.cleanup();
|
|
50661
|
-
const restarted = await recreateSessionAndValidate(options);
|
|
50662
|
-
if (!restarted) process.exit(1);
|
|
50663
|
-
} else {
|
|
50664
|
-
const shouldRestart = await logger_logger.confirm("Would you like to restart the watch session?", true);
|
|
50665
|
-
if (shouldRestart) {
|
|
50666
|
-
session.cleanup();
|
|
50667
|
-
const restarted = await recreateSessionAndValidate(options);
|
|
50668
|
-
if (!restarted) process.exit(1);
|
|
50669
|
-
}
|
|
50697
|
+
if ("\\" === ch) {
|
|
50698
|
+
escaping = true;
|
|
50699
|
+
continue;
|
|
50670
50700
|
}
|
|
50671
|
-
|
|
50672
|
-
|
|
50673
|
-
|
|
50674
|
-
|
|
50675
|
-
if (!shouldContinue) {
|
|
50676
|
-
logger_logger.warn("Watch cancelled. Commit, stash, or discard your changes, then try again.");
|
|
50677
|
-
session.cleanup();
|
|
50678
|
-
process.exit(0);
|
|
50679
|
-
}
|
|
50701
|
+
if (quote) {
|
|
50702
|
+
if (ch === quote) quote = null;
|
|
50703
|
+
else current += ch;
|
|
50704
|
+
continue;
|
|
50680
50705
|
}
|
|
50681
|
-
|
|
50682
|
-
|
|
50683
|
-
|
|
50684
|
-
|
|
50685
|
-
|
|
50686
|
-
|
|
50687
|
-
|
|
50706
|
+
if ('"' === ch || "'" === ch) {
|
|
50707
|
+
quote = ch;
|
|
50708
|
+
continue;
|
|
50709
|
+
}
|
|
50710
|
+
if (/\s/.test(ch)) {
|
|
50711
|
+
if (current) {
|
|
50712
|
+
tokens.push(current);
|
|
50713
|
+
current = "";
|
|
50714
|
+
}
|
|
50715
|
+
continue;
|
|
50688
50716
|
}
|
|
50717
|
+
current += ch;
|
|
50718
|
+
}
|
|
50719
|
+
if (escaping) current += "\\";
|
|
50720
|
+
if (quote) throw new Error(`Unterminated quote in command: ${command}`);
|
|
50721
|
+
if (current) tokens.push(current);
|
|
50722
|
+
return tokens;
|
|
50723
|
+
}
|
|
50724
|
+
function quoteForPosixShell(value) {
|
|
50725
|
+
if ("" === value) return "''";
|
|
50726
|
+
return `'${value.replace(/'/g, "'\"'\"'")}'`;
|
|
50727
|
+
}
|
|
50728
|
+
function quoteForCmdShell(value) {
|
|
50729
|
+
const escaped = value.replace(/[%^&|<>()"!]/g, "^$&");
|
|
50730
|
+
return `"${escaped}"`;
|
|
50731
|
+
}
|
|
50732
|
+
function buildShellCommandLine(tokens) {
|
|
50733
|
+
if ("win32" === process.platform) return tokens.map(quoteForCmdShell).join(" ");
|
|
50734
|
+
return tokens.map(quoteForPosixShell).join(" ");
|
|
50735
|
+
}
|
|
50736
|
+
async function openPathInEditorOrDefault(targetPath, preferredEditorCommand, deps = defaultDeps) {
|
|
50737
|
+
if (preferredEditorCommand) if (deps.isCommandAvailable(preferredEditorCommand)) try {
|
|
50738
|
+
const tokens = parseCommandTokens(preferredEditorCommand);
|
|
50739
|
+
if (0 === tokens.length) throw new Error("empty command");
|
|
50740
|
+
await deps.spawnShellCommand(buildShellCommandLine([
|
|
50741
|
+
...tokens,
|
|
50742
|
+
targetPath
|
|
50743
|
+
]));
|
|
50744
|
+
return;
|
|
50745
|
+
} catch (error) {
|
|
50746
|
+
logger_logger.warn(`Failed to open preferred editor '${preferredEditorCommand}': ${errors_getErrorMessage(error)}. Falling back to the system default app.`);
|
|
50689
50747
|
}
|
|
50690
|
-
|
|
50748
|
+
else logger_logger.warn(`Preferred editor command '${preferredEditorCommand}' was not found in PATH. Falling back to the system default app.`);
|
|
50749
|
+
await deps.openSystem(targetPath);
|
|
50691
50750
|
}
|
|
50692
|
-
|
|
50693
|
-
|
|
50694
|
-
|
|
50695
|
-
|
|
50696
|
-
|
|
50697
|
-
|
|
50698
|
-
|
|
50699
|
-
|
|
50700
|
-
|
|
50701
|
-
|
|
50702
|
-
|
|
50703
|
-
|
|
50704
|
-
|
|
50705
|
-
|
|
50706
|
-
|
|
50707
|
-
|
|
50708
|
-
|
|
50709
|
-
|
|
50710
|
-
|
|
50711
|
-
|
|
50712
|
-
|
|
50713
|
-
|
|
50714
|
-
if (binding.url && !explicitUrl) {
|
|
50715
|
-
anvilUrl = normalizeAnvilUrl(binding.url);
|
|
50716
|
-
logger_logger.verbose(chalk_source.cyan("Resolved URL from binding for app ID: ") + chalk_source.bold(anvilUrl));
|
|
50717
|
-
}
|
|
50718
|
-
if (binding.username && !explicitUsername) {
|
|
50719
|
-
username = binding.username;
|
|
50720
|
-
logger_logger.verbose(chalk_source.cyan("Resolved username from binding for app ID: ") + chalk_source.bold(username));
|
|
50721
|
-
}
|
|
50722
|
-
const remoteInfo = lookupRemoteInfoForAppId(explicitAppId, detectedFromAllRemotes);
|
|
50723
|
-
if (remoteInfo.detectedUrl && !explicitUrl && !anvilUrl) {
|
|
50724
|
-
anvilUrl = normalizeAnvilUrl(remoteInfo.detectedUrl);
|
|
50725
|
-
logger_logger.verbose(chalk_source.cyan("Resolved URL from remote for app ID: ") + chalk_source.bold(anvilUrl));
|
|
50726
|
-
}
|
|
50727
|
-
if (remoteInfo.detectedUsername && !explicitUsername && !username) {
|
|
50728
|
-
username = remoteInfo.detectedUsername;
|
|
50729
|
-
logger_logger.verbose(chalk_source.cyan("Resolved username from remote for app ID: ") + chalk_source.bold(username));
|
|
50730
|
-
}
|
|
50731
|
-
} else {
|
|
50732
|
-
logger_logger.verbose(chalk_source.cyan("No app ID provided, attempting auto-detection..."));
|
|
50733
|
-
if (0 === filteredCandidates.length) {
|
|
50734
|
-
logger_logger.verbose(chalk_source.gray("No app IDs found in git remotes."));
|
|
50735
|
-
const resolvedFallbackUrl = await resolveUrlForFallback(explicitUrl);
|
|
50736
|
-
if (null === resolvedFallbackUrl) {
|
|
50737
|
-
logger_logger.warn("Operation cancelled.");
|
|
50738
|
-
process.exit(0);
|
|
50739
|
-
}
|
|
50740
|
-
fallbackUrl = normalizeAnvilUrl(resolvedFallbackUrl);
|
|
50741
|
-
const lookupDecision = await confirmReverseLookupWithResolvedUser(fallbackUrl, username);
|
|
50742
|
-
if (null === lookupDecision) {
|
|
50743
|
-
logger_logger.warn("Operation cancelled.");
|
|
50744
|
-
process.exit(0);
|
|
50745
|
-
}
|
|
50746
|
-
username = lookupDecision.username;
|
|
50747
|
-
if (lookupDecision.shouldContinue) {
|
|
50748
|
-
logger_logger.progress("detect", `Searching ${fallbackUrl} ${username ? `for ${username}` : ""} for matching app IDs...`);
|
|
50749
|
-
const reverseLookupCandidates = await detectAppIdsByCommitLookup(repoPath, {
|
|
50750
|
-
anvilUrl: fallbackUrl,
|
|
50751
|
-
username,
|
|
50752
|
-
includeRemotes: false
|
|
50753
|
-
});
|
|
50754
|
-
logger_logger.progressEnd("detect");
|
|
50755
|
-
for (const c of reverseLookupCandidates)filteredCandidates.push({
|
|
50756
|
-
...c,
|
|
50757
|
-
detectedUrl: fallbackUrl
|
|
50758
|
-
});
|
|
50759
|
-
}
|
|
50760
|
-
}
|
|
50761
|
-
if (filteredCandidates.length > 0) {
|
|
50762
|
-
for (const c of filteredCandidates)logger_logger.verbose(chalk_source.gray(` Found: ${formatCandidateLabel(c)}`));
|
|
50763
|
-
if (filteredCandidates.length > 1) logger_logger.verbose(chalk_source.yellow(`Found ${filteredCandidates.length} potential app IDs`));
|
|
50764
|
-
}
|
|
50765
|
-
if (useFirst && filteredCandidates.length > 0) {
|
|
50766
|
-
const selected = filteredCandidates[0];
|
|
50767
|
-
finalAppId = selected.appId;
|
|
50768
|
-
if (selected.detectedUrl) anvilUrl = normalizeAnvilUrl(selected.detectedUrl);
|
|
50769
|
-
if (selected.detectedUsername && !username) username = selected.detectedUsername;
|
|
50770
|
-
logger_logger.success("Auto-selected first app ID: " + chalk_source.bold(finalAppId));
|
|
50771
|
-
} else {
|
|
50772
|
-
const selected = await selectAppId(filteredCandidates);
|
|
50773
|
-
if (!selected) {
|
|
50774
|
-
logger_logger.error("No app ID provided. Cannot continue without an app ID.");
|
|
50775
|
-
process.exit(1);
|
|
50776
|
-
}
|
|
50777
|
-
finalAppId = selected.appId;
|
|
50778
|
-
if (selected.detectedUrl) anvilUrl = normalizeAnvilUrl(selected.detectedUrl);
|
|
50779
|
-
if (selected.detectedUsername && !username) username = selected.detectedUsername;
|
|
50780
|
-
}
|
|
50781
|
-
}
|
|
50782
|
-
const binding = await getAppAuthBinding(repoPath, finalAppId);
|
|
50783
|
-
if (binding.url && !explicitUrl) {
|
|
50784
|
-
anvilUrl = normalizeAnvilUrl(binding.url);
|
|
50785
|
-
logger_logger.verbose(chalk_source.cyan("Using app binding URL: ") + chalk_source.bold(anvilUrl));
|
|
50786
|
-
}
|
|
50787
|
-
if (binding.username && !explicitUsername) {
|
|
50788
|
-
username = binding.username;
|
|
50789
|
-
logger_logger.verbose(chalk_source.cyan("Using app binding username: ") + chalk_source.bold(username));
|
|
50790
|
-
}
|
|
50791
|
-
shouldPersistUsernameBinding = !binding.username && !explicitUsername;
|
|
50792
|
-
if (explicitUrl) anvilUrl = normalizeAnvilUrl(explicitUrl);
|
|
50793
|
-
else if (!anvilUrl) if (fallbackUrl) anvilUrl = fallbackUrl;
|
|
50794
|
-
else {
|
|
50795
|
-
const resolvedFallbackUrl = await resolveUrlForFallback();
|
|
50796
|
-
if (null === resolvedFallbackUrl) {
|
|
50797
|
-
logger_logger.warn("Operation cancelled.");
|
|
50798
|
-
process.exit(0);
|
|
50799
|
-
}
|
|
50800
|
-
anvilUrl = normalizeAnvilUrl(resolvedFallbackUrl);
|
|
50801
|
-
}
|
|
50802
|
-
anvilUrl = normalizeAnvilUrl(anvilUrl);
|
|
50803
|
-
logger_logger.verbose(chalk_source.green("Using app ID: ") + chalk_source.bold(finalAppId));
|
|
50804
|
-
logger_logger.verbose(chalk_source.cyan("Using Anvil URL: ") + chalk_source.bold(anvilUrl));
|
|
50805
|
-
const resolvedUsername = await resolveUsernameForUrl(anvilUrl, username);
|
|
50806
|
-
if (null === resolvedUsername) {
|
|
50807
|
-
logger_logger.warn("Operation cancelled.");
|
|
50808
|
-
process.exit(0);
|
|
50809
|
-
}
|
|
50810
|
-
username = resolvedUsername;
|
|
50811
|
-
if (shouldPersistUsernameBinding && username && auth_getAccountsForUrl(anvilUrl).length > 1) {
|
|
50812
|
-
await setAppAuthBinding(repoPath, finalAppId, {
|
|
50813
|
-
url: anvilUrl,
|
|
50814
|
-
username
|
|
50815
|
-
});
|
|
50816
|
-
logger_logger.verbose(chalk_source.cyan("Saved app account binding for future non-interactive use."));
|
|
50817
|
-
}
|
|
50818
|
-
if (username) logger_logger.verbose(chalk_source.cyan("Using account: ") + chalk_source.bold(username));
|
|
50819
|
-
if (!hasTokensForUrl(anvilUrl, username)) {
|
|
50820
|
-
if (username) logger_logger.error(`Not logged in to ${anvilUrl} as ${username}`);
|
|
50821
|
-
else logger_logger.error(`Not logged in to ${anvilUrl}`);
|
|
50822
|
-
logger_logger.verbose(chalk_source.yellow("Please log in first:"));
|
|
50823
|
-
console.log(chalk_source.cyan(` anvil login ${anvilUrl.replace(/^https?:\/\//, "")}`));
|
|
50824
|
-
process.exit(1);
|
|
50825
|
-
}
|
|
50826
|
-
logger_logger.verbose(chalk_source.green("✓ Authentication tokens found"));
|
|
50827
|
-
logger_logger.progress("validate", `Validating app ID: ${finalAppId}`);
|
|
50828
|
-
const appIdValidation = await validateAppId(finalAppId, anvilUrl, username);
|
|
50829
|
-
logger_logger.progressEnd("validate");
|
|
50830
|
-
if (!appIdValidation.valid) {
|
|
50831
|
-
logger_logger.error(`App ID validation failed: ${appIdValidation.error}`);
|
|
50832
|
-
logger_logger.verbose(chalk_source.yellow("This could mean:"));
|
|
50833
|
-
logger_logger.verbose(chalk_source.yellow(" • The app ID doesn't exist on the server"));
|
|
50834
|
-
logger_logger.verbose(chalk_source.yellow(" • You don't have access to this app"));
|
|
50835
|
-
logger_logger.verbose(chalk_source.yellow(" • There's a network or authentication issue"));
|
|
50836
|
-
process.exit(1);
|
|
50837
|
-
}
|
|
50838
|
-
logger_logger.verbose(chalk_source.green(`✔ App ID validated successfully`));
|
|
50839
|
-
if (appIdValidation.app_name) logger_logger.verbose(chalk_source.gray(` App name: ${appIdValidation.app_name}`));
|
|
50840
|
-
if (stagedOnly) logger_logger.info(chalk_source.yellow("▸ Staged-only mode: Only staged changes will be synced"));
|
|
50841
|
-
if (autoMode) logger_logger.info(chalk_source.cyan("▸ Auto mode: Will automatically restart on branch changes and sync when behind"));
|
|
50842
|
-
logger_logger.progress("init", "Initializing watch session...");
|
|
50843
|
-
const session = await api_watch(repoPath, finalAppId, anvilUrl, stagedOnly, username);
|
|
50844
|
-
logger_logger.progressEnd("init");
|
|
50845
|
-
logger_logger.verbose(chalk_source.blue("Watching for file changes..."));
|
|
50846
|
-
const started = await checkSyncStatusAndStart(session, {
|
|
50847
|
-
autoMode,
|
|
50848
|
-
repoPath,
|
|
50849
|
-
appId: finalAppId,
|
|
50850
|
-
anvilUrl,
|
|
50851
|
-
stagedOnly,
|
|
50852
|
-
username
|
|
50853
|
-
});
|
|
50854
|
-
if (!started) process.exit(1);
|
|
50855
|
-
} catch (e) {
|
|
50856
|
-
logger_logger.error("Error: " + errors_getErrorMessage(e));
|
|
50857
|
-
process.exit(1);
|
|
50858
|
-
}
|
|
50859
|
-
}
|
|
50860
|
-
function registerWatchCommand(program) {
|
|
50861
|
-
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)=>{
|
|
50862
|
-
if (void 0 !== options.verbose && logger_logger instanceof CLILogger) logger_logger.setVerbose(options.verbose);
|
|
50863
|
-
await handleWatchCommand({
|
|
50864
|
-
path,
|
|
50865
|
-
appid: options.appid,
|
|
50866
|
-
useFirst: options.first,
|
|
50867
|
-
stagedOnly: options.stagedOnly,
|
|
50868
|
-
autoMode: options.auto,
|
|
50869
|
-
verbose: options.verbose,
|
|
50870
|
-
url: options.url,
|
|
50871
|
-
user: options.user
|
|
50872
|
-
});
|
|
50873
|
-
});
|
|
50874
|
-
return watchCommand;
|
|
50751
|
+
function decideFallbackUrl(explicitUrl, availableUrls = getAvailableAnvilUrls()) {
|
|
50752
|
+
if (explicitUrl) return {
|
|
50753
|
+
source: "explicit",
|
|
50754
|
+
url: normalizeAnvilUrl(explicitUrl)
|
|
50755
|
+
};
|
|
50756
|
+
if (availableUrls.length > 1) return {
|
|
50757
|
+
source: "available-multiple",
|
|
50758
|
+
urls: availableUrls
|
|
50759
|
+
};
|
|
50760
|
+
if (1 === availableUrls.length) return {
|
|
50761
|
+
source: "available-single",
|
|
50762
|
+
url: availableUrls[0]
|
|
50763
|
+
};
|
|
50764
|
+
const fromConfig = getConfig("anvilUrl");
|
|
50765
|
+
if ("string" == typeof fromConfig && fromConfig.trim()) return {
|
|
50766
|
+
source: "config",
|
|
50767
|
+
url: normalizeAnvilUrl(fromConfig.trim())
|
|
50768
|
+
};
|
|
50769
|
+
return {
|
|
50770
|
+
source: "default",
|
|
50771
|
+
url: isDevMode() ? "http://localhost:3000" : "https://anvil.works"
|
|
50772
|
+
};
|
|
50875
50773
|
}
|
|
50876
|
-
|
|
50877
|
-
|
|
50878
|
-
|
|
50879
|
-
|
|
50880
|
-
|
|
50881
|
-
|
|
50882
|
-
|
|
50883
|
-
}
|
|
50884
|
-
|
|
50885
|
-
|
|
50774
|
+
function decideUsernameForUrl(accounts) {
|
|
50775
|
+
if (0 === accounts.length) return {
|
|
50776
|
+
source: "none"
|
|
50777
|
+
};
|
|
50778
|
+
if (1 === accounts.length) return {
|
|
50779
|
+
source: "single",
|
|
50780
|
+
username: accounts[0]
|
|
50781
|
+
};
|
|
50782
|
+
return {
|
|
50783
|
+
source: "multiple",
|
|
50784
|
+
usernames: [
|
|
50785
|
+
...accounts
|
|
50786
|
+
]
|
|
50787
|
+
};
|
|
50886
50788
|
}
|
|
50887
|
-
function
|
|
50888
|
-
|
|
50889
|
-
|
|
50890
|
-
|
|
50891
|
-
|
|
50789
|
+
async function resolveUsernameForUrl(anvilUrl, explicitUsername, promptMessage = "Multiple accounts found. Which account owns this app?") {
|
|
50790
|
+
if (explicitUsername) return explicitUsername;
|
|
50791
|
+
const decision = decideUsernameForUrl(auth_getAccountsForUrl(anvilUrl));
|
|
50792
|
+
if ("none" === decision.source) return;
|
|
50793
|
+
if ("single" === decision.source) {
|
|
50794
|
+
logger_logger.verbose(chalk_source.cyan("Auto-selected account: ") + chalk_source.bold(decision.username));
|
|
50795
|
+
return decision.username;
|
|
50892
50796
|
}
|
|
50797
|
+
const choices = decision.usernames.map((acct)=>({
|
|
50798
|
+
name: acct,
|
|
50799
|
+
value: acct
|
|
50800
|
+
}));
|
|
50801
|
+
choices.push({
|
|
50802
|
+
name: "Cancel",
|
|
50803
|
+
value: null
|
|
50804
|
+
});
|
|
50805
|
+
return logger_logger.select(promptMessage, choices, decision.usernames[0]);
|
|
50893
50806
|
}
|
|
50894
|
-
function
|
|
50895
|
-
|
|
50896
|
-
return
|
|
50807
|
+
async function confirmReverseLookupWithResolvedUser(anvilUrl, username) {
|
|
50808
|
+
const resolvedUsername = await resolveUsernameForUrl(anvilUrl, username, `Multiple accounts found for ${anvilUrl}. Which account should be used for app lookup?`);
|
|
50809
|
+
if (null === resolvedUsername) return null;
|
|
50810
|
+
const shouldContinue = await logger_logger.confirm(`Search ${anvilUrl} ${resolvedUsername ? `for ${resolvedUsername}` : ""} for matching app IDs? (slower)`, true);
|
|
50811
|
+
return {
|
|
50812
|
+
username: resolvedUsername,
|
|
50813
|
+
shouldContinue
|
|
50814
|
+
};
|
|
50897
50815
|
}
|
|
50898
|
-
|
|
50899
|
-
|
|
50816
|
+
async function resolveUrlForFallback(explicitUrl) {
|
|
50817
|
+
const decision = decideFallbackUrl(explicitUrl);
|
|
50818
|
+
if ("available-multiple" !== decision.source) return decision.url;
|
|
50819
|
+
const choices = decision.urls.map((url)=>({
|
|
50820
|
+
name: url,
|
|
50821
|
+
value: url
|
|
50822
|
+
}));
|
|
50823
|
+
choices.push({
|
|
50824
|
+
name: "Cancel",
|
|
50825
|
+
value: null
|
|
50826
|
+
});
|
|
50827
|
+
const selectedUrl = await logger_logger.select("Multiple logged-in Anvil URLs found. Which one would you like to use?", choices, decision.urls[0]);
|
|
50828
|
+
return selectedUrl;
|
|
50829
|
+
}
|
|
50830
|
+
function resolveWatchOpenPath(repoPath) {
|
|
50831
|
+
return external_path_default().resolve(repoPath);
|
|
50832
|
+
}
|
|
50833
|
+
async function openWatchPath(targetPath, deps) {
|
|
50834
|
+
const preferredEditor = String(getConfig("preferredEditor") || "").trim();
|
|
50835
|
+
const preferredEditorCommand = preferredEditor ? getPreferredEditorCommand(preferredEditor) : "";
|
|
50836
|
+
await openPathInEditorOrDefault(targetPath, preferredEditorCommand, deps);
|
|
50837
|
+
logger_logger.info(chalk_source.gray(`Opened ${targetPath}`));
|
|
50838
|
+
}
|
|
50839
|
+
async function selectAppId(candidates) {
|
|
50840
|
+
if (0 === candidates.length) {
|
|
50841
|
+
logger_logger.warn("Could not auto-detect app ID from repository.");
|
|
50842
|
+
const rl = external_readline_namespaceObject.createInterface({
|
|
50843
|
+
input: process.stdin,
|
|
50844
|
+
output: process.stdout
|
|
50845
|
+
});
|
|
50846
|
+
const manualAppId = await new Promise((resolve)=>{
|
|
50847
|
+
const handleInterrupt = ()=>{
|
|
50848
|
+
rl.close();
|
|
50849
|
+
logger_logger.warn("Operation cancelled by user.");
|
|
50850
|
+
resolve(null);
|
|
50851
|
+
};
|
|
50852
|
+
rl.on("SIGINT", handleInterrupt);
|
|
50853
|
+
rl.question(chalk_source.cyan("Please enter app ID manually (or press Enter to exit): "), (answer)=>{
|
|
50854
|
+
rl.removeListener("SIGINT", handleInterrupt);
|
|
50855
|
+
rl.close();
|
|
50856
|
+
const trimmed = answer.trim();
|
|
50857
|
+
trimmed ? resolve(trimmed) : resolve(null);
|
|
50858
|
+
});
|
|
50859
|
+
});
|
|
50860
|
+
if (manualAppId) return {
|
|
50861
|
+
appId: manualAppId,
|
|
50862
|
+
source: "config",
|
|
50863
|
+
description: "Manual entry"
|
|
50864
|
+
};
|
|
50865
|
+
return null;
|
|
50866
|
+
}
|
|
50867
|
+
const choices = candidates.map((candidate, index)=>({
|
|
50868
|
+
name: formatCandidateLabel(candidate),
|
|
50869
|
+
value: index
|
|
50870
|
+
}));
|
|
50871
|
+
choices.push({
|
|
50872
|
+
name: "Cancel",
|
|
50873
|
+
value: null
|
|
50874
|
+
});
|
|
50900
50875
|
try {
|
|
50901
|
-
|
|
50876
|
+
const promptText = 1 === candidates.length ? "Confirm the detected app ID:" : "Select an app ID:";
|
|
50877
|
+
const answer = await logger_logger.prompt([
|
|
50878
|
+
{
|
|
50879
|
+
type: "list",
|
|
50880
|
+
name: "appId",
|
|
50881
|
+
message: promptText,
|
|
50882
|
+
choices: choices,
|
|
50883
|
+
pageSize: 10
|
|
50884
|
+
}
|
|
50885
|
+
]);
|
|
50886
|
+
if (null === answer.appId) {
|
|
50887
|
+
const rl = external_readline_namespaceObject.createInterface({
|
|
50888
|
+
input: process.stdin,
|
|
50889
|
+
output: process.stdout
|
|
50890
|
+
});
|
|
50891
|
+
const manualAppId = await new Promise((resolve)=>{
|
|
50892
|
+
rl.question(chalk_source.cyan("Please enter app ID manually (or press Enter to exit): "), (answer)=>{
|
|
50893
|
+
rl.close();
|
|
50894
|
+
const trimmed = answer.trim();
|
|
50895
|
+
trimmed ? resolve(trimmed) : resolve(null);
|
|
50896
|
+
});
|
|
50897
|
+
});
|
|
50898
|
+
if (manualAppId) return {
|
|
50899
|
+
appId: manualAppId,
|
|
50900
|
+
source: "config",
|
|
50901
|
+
description: "Manual entry"
|
|
50902
|
+
};
|
|
50903
|
+
return null;
|
|
50904
|
+
}
|
|
50905
|
+
return candidates[answer.appId];
|
|
50906
|
+
} catch (error) {
|
|
50907
|
+
const errorObj = error;
|
|
50908
|
+
if ("ExitPromptError" === errorObj.name || errorObj.message.includes("User force closed")) logger_logger.warn("Operation cancelled by user.");
|
|
50909
|
+
return null;
|
|
50910
|
+
}
|
|
50911
|
+
}
|
|
50912
|
+
async function pushToAnvil(options) {
|
|
50913
|
+
try {
|
|
50914
|
+
const authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
50915
|
+
const pushUrl = getGitPushUrl(options.appId, authToken, options.anvilUrl);
|
|
50916
|
+
const git = new GitService(options.repoPath);
|
|
50917
|
+
const refSpec = `${options.branchName}:${options.branchName}`;
|
|
50918
|
+
logger_logger.progress("push", "Pushing to Anvil...");
|
|
50919
|
+
await git.push(pushUrl, refSpec, options.force ?? false);
|
|
50920
|
+
logger_logger.progressEnd("push", "Pushed to Anvil");
|
|
50902
50921
|
return true;
|
|
50903
|
-
} catch
|
|
50922
|
+
} catch (e) {
|
|
50923
|
+
logger_logger.progressEnd("push", "Push failed");
|
|
50924
|
+
logger_logger.error(`Failed to push: ${errors_getErrorMessage(e)}`);
|
|
50904
50925
|
return false;
|
|
50905
50926
|
}
|
|
50906
|
-
};
|
|
50907
|
-
function isInsideContainer() {
|
|
50908
|
-
if (void 0 === cachedResult) cachedResult = hasContainerEnv() || isDocker();
|
|
50909
|
-
return cachedResult;
|
|
50910
50927
|
}
|
|
50911
|
-
|
|
50912
|
-
|
|
50913
|
-
|
|
50914
|
-
|
|
50915
|
-
|
|
50928
|
+
async function fetchAndRebaseFromAnvil(options) {
|
|
50929
|
+
const git = new GitService(options.repoPath);
|
|
50930
|
+
const tempRef = `anvil-rebase-temp-${Date.now()}`;
|
|
50931
|
+
let didStash = false;
|
|
50932
|
+
try {
|
|
50933
|
+
const authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
50934
|
+
const fetchUrl = getGitFetchUrl(options.appId, authToken, options.anvilUrl);
|
|
50935
|
+
const hasChanges = await git.hasUncommittedChanges();
|
|
50936
|
+
if (hasChanges) {
|
|
50937
|
+
logger_logger.progress("rebase", "Stashing uncommitted changes...");
|
|
50938
|
+
didStash = await git.stash("anvil-sync: stash before rebase");
|
|
50939
|
+
}
|
|
50940
|
+
logger_logger.progressUpdate("rebase", "Fetching from Anvil...");
|
|
50941
|
+
await git.fetch(fetchUrl, `+${options.branchName}:${tempRef}`);
|
|
50942
|
+
logger_logger.progressUpdate("rebase", "Rebasing...");
|
|
50943
|
+
await git.rebase(tempRef);
|
|
50944
|
+
logger_logger.progressUpdate("rebase", "Pushing rebased changes...");
|
|
50945
|
+
const pushUrl = getGitPushUrl(options.appId, authToken, options.anvilUrl);
|
|
50946
|
+
await git.push(pushUrl, `${options.branchName}:${options.branchName}`, true);
|
|
50947
|
+
logger_logger.progressEnd("rebase", "Rebased and pushed to Anvil");
|
|
50948
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50949
|
+
if (didStash) try {
|
|
50950
|
+
await git.stashPop();
|
|
50951
|
+
logger_logger.verbose(chalk_source.green("Restored uncommitted changes"));
|
|
50952
|
+
} catch (e) {
|
|
50953
|
+
logger_logger.warn("Uncommitted changes were stashed but could not be restored automatically.");
|
|
50954
|
+
logger_logger.info(chalk_source.gray(" Run: git stash pop"));
|
|
50955
|
+
}
|
|
50956
|
+
return {
|
|
50957
|
+
success: true,
|
|
50958
|
+
conflicted: false
|
|
50959
|
+
};
|
|
50960
|
+
} catch (e) {
|
|
50961
|
+
const msg = errors_getErrorMessage(e);
|
|
50962
|
+
if (msg.includes("rebase") && (msg.includes("conflict") || msg.includes("CONFLICT") || msg.includes("could not apply"))) {
|
|
50963
|
+
try {
|
|
50964
|
+
await git.rebaseAbort();
|
|
50965
|
+
} catch {}
|
|
50966
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50967
|
+
if (didStash) try {
|
|
50968
|
+
await git.stashPop();
|
|
50969
|
+
} catch {
|
|
50970
|
+
logger_logger.warn("Your uncommitted changes are in the stash. Run: git stash pop");
|
|
50971
|
+
}
|
|
50972
|
+
logger_logger.progressEnd("rebase", "Rebase failed - conflicts");
|
|
50973
|
+
return {
|
|
50974
|
+
success: false,
|
|
50975
|
+
conflicted: true
|
|
50976
|
+
};
|
|
50977
|
+
}
|
|
50978
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
50979
|
+
if (didStash) try {
|
|
50980
|
+
await git.stashPop();
|
|
50981
|
+
} catch {
|
|
50982
|
+
logger_logger.warn("Your uncommitted changes are in the stash. Run: git stash pop");
|
|
50983
|
+
}
|
|
50984
|
+
logger_logger.progressEnd("rebase", "Rebase failed");
|
|
50985
|
+
logger_logger.error(`Failed to rebase: ${msg}`);
|
|
50986
|
+
return {
|
|
50987
|
+
success: false,
|
|
50988
|
+
conflicted: false
|
|
50989
|
+
};
|
|
50916
50990
|
}
|
|
50991
|
+
}
|
|
50992
|
+
async function fetchAndHardResetFromAnvil(options) {
|
|
50993
|
+
const git = new GitService(options.repoPath);
|
|
50994
|
+
const tempRef = `anvil-reset-temp-${Date.now()}`;
|
|
50917
50995
|
try {
|
|
50918
|
-
|
|
50919
|
-
|
|
50996
|
+
const authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
50997
|
+
const fetchUrl = getGitFetchUrl(options.appId, authToken, options.anvilUrl);
|
|
50998
|
+
logger_logger.progress("reset", "Fetching from Anvil...");
|
|
50999
|
+
await git.fetch(fetchUrl, `+${options.branchName}:${tempRef}`);
|
|
51000
|
+
logger_logger.progressUpdate("reset", "Resetting to Anvil's version...");
|
|
51001
|
+
await git.reset(tempRef, "hard");
|
|
51002
|
+
logger_logger.progressEnd("reset", "Reset to Anvil's version");
|
|
51003
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
51004
|
+
return true;
|
|
51005
|
+
} catch (e) {
|
|
51006
|
+
await git.deleteRef(`refs/heads/${tempRef}`);
|
|
51007
|
+
logger_logger.progressEnd("reset", "Reset failed");
|
|
51008
|
+
logger_logger.error(`Failed to reset: ${errors_getErrorMessage(e)}`);
|
|
50920
51009
|
return false;
|
|
50921
51010
|
}
|
|
50922
|
-
};
|
|
50923
|
-
const is_wsl = external_node_process_.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
50924
|
-
const wslDrivesMountPoint = (()=>{
|
|
50925
|
-
const defaultMountPoint = '/mnt/';
|
|
50926
|
-
let mountPoint;
|
|
50927
|
-
return async function() {
|
|
50928
|
-
if (mountPoint) return mountPoint;
|
|
50929
|
-
const configFilePath = '/etc/wsl.conf';
|
|
50930
|
-
let isConfigFileExists = false;
|
|
50931
|
-
try {
|
|
50932
|
-
await external_node_fs_promises_namespaceObject.access(configFilePath, external_node_fs_promises_namespaceObject.constants.F_OK);
|
|
50933
|
-
isConfigFileExists = true;
|
|
50934
|
-
} catch {}
|
|
50935
|
-
if (!isConfigFileExists) return defaultMountPoint;
|
|
50936
|
-
const configContent = await external_node_fs_promises_namespaceObject.readFile(configFilePath, {
|
|
50937
|
-
encoding: 'utf8'
|
|
50938
|
-
});
|
|
50939
|
-
const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
|
|
50940
|
-
if (!configMountPoint) return defaultMountPoint;
|
|
50941
|
-
mountPoint = configMountPoint.groups.mountPoint.trim();
|
|
50942
|
-
mountPoint = mountPoint.endsWith('/') ? mountPoint : `${mountPoint}/`;
|
|
50943
|
-
return mountPoint;
|
|
50944
|
-
};
|
|
50945
|
-
})();
|
|
50946
|
-
const powerShellPathFromWsl = async ()=>{
|
|
50947
|
-
const mountPoint = await wslDrivesMountPoint();
|
|
50948
|
-
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
|
|
50949
|
-
};
|
|
50950
|
-
const powerShellPath = async ()=>{
|
|
50951
|
-
if (is_wsl) return powerShellPathFromWsl();
|
|
50952
|
-
return `${external_node_process_.env.SYSTEMROOT || external_node_process_.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
50953
|
-
};
|
|
50954
|
-
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
50955
|
-
const define = (value)=>Object.defineProperty(object, propertyName, {
|
|
50956
|
-
value,
|
|
50957
|
-
enumerable: true,
|
|
50958
|
-
writable: true
|
|
50959
|
-
});
|
|
50960
|
-
Object.defineProperty(object, propertyName, {
|
|
50961
|
-
configurable: true,
|
|
50962
|
-
enumerable: true,
|
|
50963
|
-
get () {
|
|
50964
|
-
const result = valueGetter();
|
|
50965
|
-
define(result);
|
|
50966
|
-
return result;
|
|
50967
|
-
},
|
|
50968
|
-
set (value) {
|
|
50969
|
-
define(value);
|
|
50970
|
-
}
|
|
50971
|
-
});
|
|
50972
|
-
return object;
|
|
50973
51011
|
}
|
|
50974
|
-
|
|
50975
|
-
|
|
50976
|
-
if (
|
|
50977
|
-
|
|
50978
|
-
|
|
50979
|
-
|
|
50980
|
-
|
|
50981
|
-
]);
|
|
50982
|
-
const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
|
|
50983
|
-
const browserId = match?.groups.id ?? 'com.apple.Safari';
|
|
50984
|
-
if ('com.apple.safari' === browserId) return 'com.apple.Safari';
|
|
50985
|
-
return browserId;
|
|
50986
|
-
}
|
|
50987
|
-
const run_applescript_execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_.execFile);
|
|
50988
|
-
async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
|
|
50989
|
-
if ('darwin' !== external_node_process_.platform) throw new Error('macOS only');
|
|
50990
|
-
const outputArguments = humanReadableOutput ? [] : [
|
|
50991
|
-
'-ss'
|
|
50992
|
-
];
|
|
50993
|
-
const execOptions = {};
|
|
50994
|
-
if (signal) execOptions.signal = signal;
|
|
50995
|
-
const { stdout } = await run_applescript_execFileAsync("osascript", [
|
|
50996
|
-
'-e',
|
|
50997
|
-
script,
|
|
50998
|
-
outputArguments
|
|
50999
|
-
], execOptions);
|
|
51000
|
-
return stdout.trim();
|
|
51001
|
-
}
|
|
51002
|
-
async function bundleName(bundleId) {
|
|
51003
|
-
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string\ntell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
51012
|
+
function getSyncStateCategory(syncStatus) {
|
|
51013
|
+
if (syncStatus?.branchMissing) return "branch-missing";
|
|
51014
|
+
if (syncStatus?.diverged) return "diverged";
|
|
51015
|
+
if (syncStatus?.ahead && !syncStatus?.behind) return "ahead";
|
|
51016
|
+
if (syncStatus?.behind && !syncStatus?.ahead) return "behind";
|
|
51017
|
+
if (syncStatus?.ahead && syncStatus?.behind) return "diverged";
|
|
51018
|
+
return "in-sync";
|
|
51004
51019
|
}
|
|
51005
|
-
|
|
51006
|
-
|
|
51007
|
-
|
|
51008
|
-
|
|
51009
|
-
|
|
51010
|
-
|
|
51011
|
-
|
|
51012
|
-
|
|
51013
|
-
|
|
51014
|
-
|
|
51015
|
-
|
|
51016
|
-
|
|
51017
|
-
|
|
51018
|
-
}
|
|
51019
|
-
|
|
51020
|
-
|
|
51021
|
-
|
|
51022
|
-
},
|
|
51023
|
-
ChromeHTML: {
|
|
51024
|
-
name: 'Chrome',
|
|
51025
|
-
id: 'com.google.chrome'
|
|
51026
|
-
},
|
|
51027
|
-
ChromeBHTML: {
|
|
51028
|
-
name: 'Chrome Beta',
|
|
51029
|
-
id: 'com.google.chrome.beta'
|
|
51030
|
-
},
|
|
51031
|
-
ChromeDHTML: {
|
|
51032
|
-
name: 'Chrome Dev',
|
|
51033
|
-
id: 'com.google.chrome.dev'
|
|
51034
|
-
},
|
|
51035
|
-
ChromiumHTM: {
|
|
51036
|
-
name: 'Chromium',
|
|
51037
|
-
id: 'org.chromium.Chromium'
|
|
51038
|
-
},
|
|
51039
|
-
BraveHTML: {
|
|
51040
|
-
name: 'Brave',
|
|
51041
|
-
id: 'com.brave.Browser'
|
|
51042
|
-
},
|
|
51043
|
-
BraveBHTML: {
|
|
51044
|
-
name: 'Brave Beta',
|
|
51045
|
-
id: 'com.brave.Browser.beta'
|
|
51046
|
-
},
|
|
51047
|
-
BraveDHTML: {
|
|
51048
|
-
name: 'Brave Dev',
|
|
51049
|
-
id: 'com.brave.Browser.dev'
|
|
51050
|
-
},
|
|
51051
|
-
BraveSSHTM: {
|
|
51052
|
-
name: 'Brave Nightly',
|
|
51053
|
-
id: 'com.brave.Browser.nightly'
|
|
51054
|
-
},
|
|
51055
|
-
FirefoxURL: {
|
|
51056
|
-
name: 'Firefox',
|
|
51057
|
-
id: 'org.mozilla.firefox'
|
|
51058
|
-
},
|
|
51059
|
-
OperaStable: {
|
|
51060
|
-
name: 'Opera',
|
|
51061
|
-
id: 'com.operasoftware.Opera'
|
|
51062
|
-
},
|
|
51063
|
-
VivaldiHTM: {
|
|
51064
|
-
name: 'Vivaldi',
|
|
51065
|
-
id: 'com.vivaldi.Vivaldi'
|
|
51066
|
-
},
|
|
51067
|
-
'IE.HTTP': {
|
|
51068
|
-
name: 'Internet Explorer',
|
|
51069
|
-
id: 'com.microsoft.ie'
|
|
51020
|
+
async function recheckSyncStatus(previousCategory, previousBranch, options) {
|
|
51021
|
+
try {
|
|
51022
|
+
logger_logger.progress("verify", "Verifying repository status...");
|
|
51023
|
+
const freshSession = await api_watch(options.repoPath, options.appId, options.anvilUrl, options.stagedOnly, options.username);
|
|
51024
|
+
logger_logger.progressEnd("verify");
|
|
51025
|
+
const currentCategory = getSyncStateCategory(freshSession.syncStatus);
|
|
51026
|
+
const currentBranch = freshSession.getBranchName() || "master";
|
|
51027
|
+
if (currentCategory !== previousCategory || currentBranch !== previousBranch) {
|
|
51028
|
+
logger_logger.warn("Repository status has changed. Re-evaluating...");
|
|
51029
|
+
return freshSession;
|
|
51030
|
+
}
|
|
51031
|
+
freshSession.cleanup();
|
|
51032
|
+
return null;
|
|
51033
|
+
} catch (e) {
|
|
51034
|
+
logger_logger.progressEnd("verify");
|
|
51035
|
+
logger_logger.verbose(chalk_source.gray(`Could not re-verify status: ${errors_getErrorMessage(e)}`));
|
|
51036
|
+
return null;
|
|
51070
51037
|
}
|
|
51071
|
-
};
|
|
51072
|
-
new Map(Object.entries(windowsBrowserProgIds));
|
|
51073
|
-
class UnknownBrowserError extends Error {
|
|
51074
51038
|
}
|
|
51075
|
-
async function
|
|
51076
|
-
|
|
51077
|
-
|
|
51078
|
-
|
|
51079
|
-
|
|
51080
|
-
|
|
51081
|
-
|
|
51082
|
-
|
|
51083
|
-
|
|
51084
|
-
|
|
51085
|
-
|
|
51086
|
-
if (!browser) throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
|
|
51087
|
-
return browser;
|
|
51039
|
+
async function recreateSessionAndValidate(options) {
|
|
51040
|
+
logger_logger.progress("init", "Restarting watch session...");
|
|
51041
|
+
try {
|
|
51042
|
+
const newSession = await api_watch(options.repoPath, options.appId, options.anvilUrl, options.stagedOnly, options.username);
|
|
51043
|
+
logger_logger.progressEnd("init");
|
|
51044
|
+
return await checkSyncStatusAndStart(newSession, options);
|
|
51045
|
+
} catch (e) {
|
|
51046
|
+
logger_logger.progressEnd("init", "Failed");
|
|
51047
|
+
logger_logger.error(`Failed to restart: ${errors_getErrorMessage(e)}`);
|
|
51048
|
+
return false;
|
|
51049
|
+
}
|
|
51088
51050
|
}
|
|
51089
|
-
|
|
51090
|
-
|
|
51091
|
-
|
|
51092
|
-
|
|
51093
|
-
|
|
51094
|
-
|
|
51095
|
-
|
|
51096
|
-
|
|
51097
|
-
|
|
51098
|
-
|
|
51051
|
+
async function checkSyncStatusAndStart(session, options) {
|
|
51052
|
+
const syncStatus = session.syncStatus;
|
|
51053
|
+
const branchName = session.getBranchName() || "master";
|
|
51054
|
+
const hasUncommitted = session.hasUncommittedChanges;
|
|
51055
|
+
const stateCategory = getSyncStateCategory(syncStatus);
|
|
51056
|
+
if (syncStatus?.branchMissing) {
|
|
51057
|
+
logger_logger.warn(`Branch '${branchName}' doesn't exist on Anvil yet.`);
|
|
51058
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
51059
|
+
let shouldPush = options.autoMode;
|
|
51060
|
+
if (options.autoMode) logger_logger.info(chalk_source.cyan("→ Auto-pushing new branch to Anvil..."));
|
|
51061
|
+
else {
|
|
51062
|
+
shouldPush = await logger_logger.confirm("Would you like to push this branch to Anvil?", true);
|
|
51063
|
+
if (shouldPush) {
|
|
51064
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
51065
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
51066
|
+
}
|
|
51067
|
+
}
|
|
51068
|
+
if (!shouldPush) {
|
|
51069
|
+
logger_logger.warn("Watch cancelled. Push your branch to Anvil, then try again.");
|
|
51070
|
+
session.cleanup();
|
|
51071
|
+
return false;
|
|
51072
|
+
}
|
|
51073
|
+
session.cleanup();
|
|
51074
|
+
const pushed = await pushToAnvil({
|
|
51075
|
+
repoPath: options.repoPath,
|
|
51076
|
+
appId: options.appId,
|
|
51077
|
+
anvilUrl: options.anvilUrl,
|
|
51078
|
+
branchName,
|
|
51079
|
+
username: options.username
|
|
51080
|
+
});
|
|
51081
|
+
if (!pushed) return false;
|
|
51082
|
+
return await recreateSessionAndValidate(options);
|
|
51099
51083
|
}
|
|
51100
|
-
if (
|
|
51101
|
-
|
|
51102
|
-
|
|
51103
|
-
|
|
51104
|
-
|
|
51105
|
-
|
|
51106
|
-
|
|
51107
|
-
|
|
51108
|
-
|
|
51109
|
-
|
|
51110
|
-
|
|
51111
|
-
|
|
51084
|
+
if (syncStatus?.behind || syncStatus?.ahead) if (syncStatus.ahead && !syncStatus.behind) {
|
|
51085
|
+
logger_logger.warn(`Your local repository is ${syncStatus.ahead} commit(s) ahead of Anvil.`);
|
|
51086
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
51087
|
+
let shouldPush = options.autoMode;
|
|
51088
|
+
if (options.autoMode) logger_logger.info(chalk_source.cyan("→ Auto-pushing to Anvil..."));
|
|
51089
|
+
else {
|
|
51090
|
+
const action = await logger_logger.select("What would you like to do?", [
|
|
51091
|
+
{
|
|
51092
|
+
name: "Push your changes to Anvil (recommended)",
|
|
51093
|
+
value: "push"
|
|
51094
|
+
},
|
|
51095
|
+
{
|
|
51096
|
+
name: "Exit and handle manually",
|
|
51097
|
+
value: "exit"
|
|
51098
|
+
}
|
|
51099
|
+
], "push");
|
|
51100
|
+
shouldPush = "push" === action;
|
|
51101
|
+
if (shouldPush) {
|
|
51102
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
51103
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
51104
|
+
}
|
|
51105
|
+
}
|
|
51106
|
+
if (!shouldPush) {
|
|
51107
|
+
logger_logger.warn("Watch cancelled.");
|
|
51108
|
+
session.cleanup();
|
|
51109
|
+
return false;
|
|
51110
|
+
}
|
|
51111
|
+
session.cleanup();
|
|
51112
|
+
const pushed = await pushToAnvil({
|
|
51113
|
+
repoPath: options.repoPath,
|
|
51114
|
+
appId: options.appId,
|
|
51115
|
+
anvilUrl: options.anvilUrl,
|
|
51116
|
+
branchName,
|
|
51117
|
+
username: options.username
|
|
51118
|
+
});
|
|
51119
|
+
if (!pushed) return false;
|
|
51120
|
+
return await recreateSessionAndValidate(options);
|
|
51121
|
+
} else if (syncStatus.diverged) {
|
|
51122
|
+
logger_logger.warn("Your local repository has diverged from Anvil.");
|
|
51123
|
+
logger_logger.info(chalk_source.gray(` You are ${syncStatus.ahead} commit(s) ahead and ${syncStatus.behind} commit(s) behind.`));
|
|
51124
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
51125
|
+
session.cleanup();
|
|
51126
|
+
if (options.autoMode) {
|
|
51127
|
+
logger_logger.info(chalk_source.cyan("→ Auto-rebasing onto Anvil's version..."));
|
|
51128
|
+
const result = await fetchAndRebaseFromAnvil({
|
|
51129
|
+
repoPath: options.repoPath,
|
|
51130
|
+
appId: options.appId,
|
|
51131
|
+
anvilUrl: options.anvilUrl,
|
|
51132
|
+
branchName,
|
|
51133
|
+
username: options.username
|
|
51134
|
+
});
|
|
51135
|
+
if (result.conflicted) {
|
|
51136
|
+
logger_logger.error("Rebase failed due to conflicts. Please resolve manually:");
|
|
51137
|
+
logger_logger.info(chalk_source.gray(" 1. Run: git fetch anvil && git rebase anvil/" + branchName));
|
|
51138
|
+
logger_logger.info(chalk_source.gray(" 2. Resolve conflicts, then: git rebase --continue"));
|
|
51139
|
+
logger_logger.info(chalk_source.gray(" 3. Push: git push anvil " + branchName));
|
|
51140
|
+
return false;
|
|
51141
|
+
}
|
|
51142
|
+
if (!result.success) return false;
|
|
51143
|
+
return await recreateSessionAndValidate(options);
|
|
51144
|
+
}
|
|
51145
|
+
const action = await logger_logger.select("How would you like to resolve this?", [
|
|
51146
|
+
{
|
|
51147
|
+
name: "Pull from Anvil and rebase your changes on top (recommended)",
|
|
51148
|
+
value: "rebase"
|
|
51149
|
+
},
|
|
51150
|
+
{
|
|
51151
|
+
name: "Discard your local commits and use Anvil's version",
|
|
51152
|
+
value: "reset"
|
|
51153
|
+
},
|
|
51154
|
+
{
|
|
51155
|
+
name: "Push your version to Anvil (overwrites remote)",
|
|
51156
|
+
value: "push"
|
|
51157
|
+
},
|
|
51158
|
+
{
|
|
51159
|
+
name: "Exit and handle manually",
|
|
51160
|
+
value: "exit"
|
|
51161
|
+
}
|
|
51162
|
+
], "rebase");
|
|
51163
|
+
if ("exit" === action) {
|
|
51164
|
+
logger_logger.warn("Watch cancelled.");
|
|
51165
|
+
return false;
|
|
51166
|
+
}
|
|
51167
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
51168
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
51169
|
+
if ("rebase" === action) {
|
|
51170
|
+
const result = await fetchAndRebaseFromAnvil({
|
|
51171
|
+
repoPath: options.repoPath,
|
|
51172
|
+
appId: options.appId,
|
|
51173
|
+
anvilUrl: options.anvilUrl,
|
|
51174
|
+
branchName,
|
|
51175
|
+
username: options.username
|
|
51176
|
+
});
|
|
51177
|
+
if (result.conflicted) {
|
|
51178
|
+
logger_logger.error("Rebase failed due to conflicts. Please resolve manually:");
|
|
51179
|
+
logger_logger.info(chalk_source.gray(" 1. Run: git fetch anvil && git rebase anvil/" + branchName));
|
|
51180
|
+
logger_logger.info(chalk_source.gray(" 2. Resolve conflicts, then: git rebase --continue"));
|
|
51181
|
+
logger_logger.info(chalk_source.gray(" 3. Push: git push anvil " + branchName));
|
|
51182
|
+
return false;
|
|
51183
|
+
}
|
|
51184
|
+
if (!result.success) return false;
|
|
51185
|
+
return await recreateSessionAndValidate(options);
|
|
51186
|
+
}
|
|
51187
|
+
if ("reset" === action) {
|
|
51188
|
+
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?`;
|
|
51189
|
+
const confirmed = await logger_logger.confirm(resetWarning, false);
|
|
51190
|
+
if (!confirmed) {
|
|
51191
|
+
logger_logger.warn("Watch cancelled.");
|
|
51192
|
+
return false;
|
|
51193
|
+
}
|
|
51194
|
+
const reset = await fetchAndHardResetFromAnvil({
|
|
51195
|
+
repoPath: options.repoPath,
|
|
51196
|
+
appId: options.appId,
|
|
51197
|
+
anvilUrl: options.anvilUrl,
|
|
51198
|
+
branchName,
|
|
51199
|
+
username: options.username
|
|
51200
|
+
});
|
|
51201
|
+
if (!reset) return false;
|
|
51202
|
+
return await recreateSessionAndValidate(options);
|
|
51203
|
+
}
|
|
51204
|
+
if ("push" === action) {
|
|
51205
|
+
const confirmed = await logger_logger.confirm("This will overwrite Anvil's version. Are you sure?", false);
|
|
51206
|
+
if (!confirmed) {
|
|
51207
|
+
logger_logger.warn("Watch cancelled.");
|
|
51208
|
+
return false;
|
|
51209
|
+
}
|
|
51210
|
+
const pushed = await pushToAnvil({
|
|
51211
|
+
repoPath: options.repoPath,
|
|
51212
|
+
appId: options.appId,
|
|
51213
|
+
anvilUrl: options.anvilUrl,
|
|
51214
|
+
branchName,
|
|
51215
|
+
username: options.username,
|
|
51216
|
+
force: true
|
|
51217
|
+
});
|
|
51218
|
+
if (!pushed) return false;
|
|
51219
|
+
return await recreateSessionAndValidate(options);
|
|
51220
|
+
}
|
|
51221
|
+
} else {
|
|
51222
|
+
logger_logger.warn(`Your local repository is ${syncStatus.behind} commit(s) behind Anvil.`);
|
|
51223
|
+
logger_logger.verbose(chalk_source.gray(" You need to sync to the latest version before watching."));
|
|
51224
|
+
if (hasUncommitted) logger_logger.info(chalk_source.gray(" You also have uncommitted changes."));
|
|
51225
|
+
let shouldSync = options.autoMode;
|
|
51226
|
+
if (options.autoMode) logger_logger.info(chalk_source.cyan("→ Auto-syncing to latest version..."));
|
|
51227
|
+
else {
|
|
51228
|
+
shouldSync = await logger_logger.confirm("Would you like to sync to the latest version from Anvil now?", true);
|
|
51229
|
+
if (shouldSync) {
|
|
51230
|
+
const changed = await recheckSyncStatus(stateCategory, branchName, options);
|
|
51231
|
+
if (changed) return await checkSyncStatusAndStart(changed, options);
|
|
51232
|
+
}
|
|
51233
|
+
}
|
|
51234
|
+
if (!shouldSync) {
|
|
51235
|
+
logger_logger.warn("Watch cancelled. Please sync manually before watching.");
|
|
51236
|
+
session.cleanup();
|
|
51237
|
+
return false;
|
|
51238
|
+
}
|
|
51239
|
+
session.cleanup();
|
|
51240
|
+
let authToken;
|
|
51241
|
+
try {
|
|
51242
|
+
authToken = await auth_getValidAuthToken(options.anvilUrl, options.username);
|
|
51243
|
+
} catch (e) {
|
|
51244
|
+
logger_logger.error("Not logged in. Please log in first.");
|
|
51245
|
+
process.exit(1);
|
|
51246
|
+
}
|
|
51247
|
+
logger_logger.progress("sync-latest", "Syncing to latest version from Anvil...");
|
|
51248
|
+
try {
|
|
51249
|
+
const newCommitId = await syncToLatest(options.repoPath, options.appId, options.anvilUrl, authToken, branchName, options.username);
|
|
51250
|
+
logger_logger.progressEnd("sync-latest", `Synced to latest version: ${newCommitId.substring(0, 8)}`);
|
|
51251
|
+
} catch (e) {
|
|
51252
|
+
logger_logger.progressEnd("sync-latest", "Failed");
|
|
51253
|
+
logger_logger.error(`Failed to sync: ${errors_getErrorMessage(e)}`);
|
|
51254
|
+
process.exit(1);
|
|
51255
|
+
}
|
|
51256
|
+
return await recreateSessionAndValidate(options);
|
|
51112
51257
|
}
|
|
51113
|
-
|
|
51114
|
-
|
|
51258
|
+
await startWatchingWithEventHandlers(session, options);
|
|
51259
|
+
return true;
|
|
51115
51260
|
}
|
|
51116
|
-
|
|
51117
|
-
|
|
51118
|
-
|
|
51119
|
-
|
|
51120
|
-
|
|
51121
|
-
|
|
51122
|
-
|
|
51123
|
-
|
|
51124
|
-
|
|
51125
|
-
|
|
51126
|
-
|
|
51127
|
-
|
|
51128
|
-
|
|
51129
|
-
|
|
51130
|
-
|
|
51131
|
-
|
|
51132
|
-
|
|
51261
|
+
async function startWatchingWithEventHandlers(session, options) {
|
|
51262
|
+
const { autoMode, repoPath, appId, anvilUrl, stagedOnly } = options;
|
|
51263
|
+
session.on("branch-changed", async ({ oldBranch, newBranch })=>{
|
|
51264
|
+
try {
|
|
51265
|
+
session.cleanup();
|
|
51266
|
+
logger_logger.warn(`Branch changed: ${chalk_source.bold(oldBranch)} → ${chalk_source.bold(newBranch)}`);
|
|
51267
|
+
logger_logger.info(chalk_source.cyan("→ Restarting watch on new branch..."));
|
|
51268
|
+
const git = esm_default(repoPath);
|
|
51269
|
+
const actualBranch = (await git.revparse([
|
|
51270
|
+
"--abbrev-ref",
|
|
51271
|
+
"HEAD"
|
|
51272
|
+
])).trim();
|
|
51273
|
+
if (actualBranch !== newBranch) logger_logger.verbose(chalk_source.yellow(`Branch changed again to ${chalk_source.bold(actualBranch)}, using that instead`));
|
|
51274
|
+
logger_logger.progress("init", "Initializing watch session...");
|
|
51275
|
+
try {
|
|
51276
|
+
const newSession = await api_watch(repoPath, appId, anvilUrl, stagedOnly, options.username);
|
|
51277
|
+
logger_logger.progressEnd("init");
|
|
51278
|
+
const started = await checkSyncStatusAndStart(newSession, options);
|
|
51279
|
+
if (!started) process.exit(0);
|
|
51280
|
+
} catch (e) {
|
|
51281
|
+
logger_logger.progressEnd("init", "Failed");
|
|
51282
|
+
logger_logger.error("Failed to restart watch: " + errors_getErrorMessage(e));
|
|
51283
|
+
process.exit(1);
|
|
51284
|
+
}
|
|
51285
|
+
} catch (error) {
|
|
51286
|
+
logger_logger.error(`Error handling branch change: ${error.message}`);
|
|
51287
|
+
process.exit(1);
|
|
51288
|
+
}
|
|
51133
51289
|
});
|
|
51134
|
-
|
|
51135
|
-
|
|
51136
|
-
|
|
51137
|
-
|
|
51138
|
-
|
|
51139
|
-
|
|
51140
|
-
};
|
|
51141
|
-
|
|
51142
|
-
|
|
51143
|
-
|
|
51290
|
+
session.on("validation-failed", ({ reason, currentBranch })=>{
|
|
51291
|
+
logger_logger.error(chalk_source.red(`Validation failed: ${reason}`));
|
|
51292
|
+
logger_logger.verbose(chalk_source.yellow(` Current branch: ${currentBranch}`));
|
|
51293
|
+
logger_logger.verbose(chalk_source.yellow(" Please restart anvil to re-validate the branch."));
|
|
51294
|
+
session.cleanup();
|
|
51295
|
+
process.exit(1);
|
|
51296
|
+
});
|
|
51297
|
+
session.on("max-retries-exceeded", async ()=>{
|
|
51298
|
+
if (autoMode) {
|
|
51299
|
+
logger_logger.info(chalk_source.cyan("→ Auto-restarting watch session..."));
|
|
51300
|
+
session.cleanup();
|
|
51301
|
+
const restarted = await recreateSessionAndValidate(options);
|
|
51302
|
+
if (!restarted) process.exit(1);
|
|
51303
|
+
} else {
|
|
51304
|
+
const shouldRestart = await logger_logger.confirm("Would you like to restart the watch session?", true);
|
|
51305
|
+
if (shouldRestart) {
|
|
51306
|
+
session.cleanup();
|
|
51307
|
+
const restarted = await recreateSessionAndValidate(options);
|
|
51308
|
+
if (!restarted) process.exit(1);
|
|
51309
|
+
}
|
|
51310
|
+
}
|
|
51311
|
+
});
|
|
51312
|
+
if (session.hasUncommittedChanges) {
|
|
51313
|
+
if (!autoMode) {
|
|
51314
|
+
const shouldContinue = await logger_logger.confirm("Continue? Your uncommitted changes will be synced to Anvil.", true);
|
|
51315
|
+
if (!shouldContinue) {
|
|
51316
|
+
logger_logger.warn("Watch cancelled. Commit, stash, or discard your changes, then try again.");
|
|
51317
|
+
session.cleanup();
|
|
51318
|
+
process.exit(0);
|
|
51319
|
+
}
|
|
51320
|
+
}
|
|
51321
|
+
logger_logger.progress("save", "Saving uncommitted changes to Anvil...");
|
|
51322
|
+
try {
|
|
51323
|
+
await session.forceSave();
|
|
51324
|
+
logger_logger.progressEnd("save");
|
|
51325
|
+
} catch (e) {
|
|
51326
|
+
logger_logger.progressEnd("save", "Failed");
|
|
51327
|
+
logger_logger.error(`Failed to save: ${errors_getErrorMessage(e)}`);
|
|
51328
|
+
}
|
|
51329
|
+
}
|
|
51330
|
+
await session.startWatching();
|
|
51144
51331
|
}
|
|
51145
|
-
|
|
51146
|
-
|
|
51147
|
-
|
|
51148
|
-
|
|
51149
|
-
|
|
51150
|
-
latestError = error;
|
|
51332
|
+
async function handleWatchCommand(options) {
|
|
51333
|
+
const invoked = process.argv[2];
|
|
51334
|
+
if ("sync" === invoked) {
|
|
51335
|
+
logger_logger.error("'sync' has been renamed to 'watch'. Please use 'anvil watch' instead.");
|
|
51336
|
+
process.exit(1);
|
|
51151
51337
|
}
|
|
51152
|
-
|
|
51153
|
-
|
|
51154
|
-
|
|
51155
|
-
|
|
51156
|
-
|
|
51157
|
-
|
|
51158
|
-
|
|
51159
|
-
|
|
51160
|
-
|
|
51161
|
-
|
|
51162
|
-
|
|
51163
|
-
|
|
51164
|
-
|
|
51165
|
-
|
|
51166
|
-
|
|
51167
|
-
|
|
51168
|
-
|
|
51169
|
-
|
|
51170
|
-
|
|
51171
|
-
...options,
|
|
51172
|
-
app: {
|
|
51173
|
-
name: appName,
|
|
51174
|
-
arguments: appArguments
|
|
51338
|
+
const { path: repoPath = process.cwd(), appid: explicitAppId, useFirst = false, stagedOnly = false, autoMode = false, url: explicitUrl, user: explicitUsername, open: openAfterValidation = false } = options;
|
|
51339
|
+
try {
|
|
51340
|
+
const validationResult = await validateAnvilApp(repoPath);
|
|
51341
|
+
if (validationResult.appName) logger_logger.info(chalk_source.green("Anvil app: ") + chalk_source.bold(validationResult.appName));
|
|
51342
|
+
const detectedFromAllRemotes = await detectAppIdsFromAllRemotes(repoPath);
|
|
51343
|
+
let filteredCandidates = filterCandidates(detectedFromAllRemotes, explicitUrl, explicitUsername);
|
|
51344
|
+
logger_logger.verbose(chalk_source.cyan(`Detected ${detectedFromAllRemotes.length} app ID(s) from git remotes`));
|
|
51345
|
+
if (filteredCandidates.length !== detectedFromAllRemotes.length) logger_logger.verbose(chalk_source.cyan(`After filtering: ${filteredCandidates.length} candidate(s)`));
|
|
51346
|
+
let finalAppId;
|
|
51347
|
+
let anvilUrl;
|
|
51348
|
+
let username = explicitUsername;
|
|
51349
|
+
let fallbackUrl;
|
|
51350
|
+
let shouldPersistUsernameBinding = false;
|
|
51351
|
+
if (explicitAppId) {
|
|
51352
|
+
finalAppId = explicitAppId;
|
|
51353
|
+
const binding = await getAppAuthBinding(repoPath, explicitAppId);
|
|
51354
|
+
if (binding.url && !explicitUrl) {
|
|
51355
|
+
anvilUrl = normalizeAnvilUrl(binding.url);
|
|
51356
|
+
logger_logger.verbose(chalk_source.cyan("Resolved URL from binding for app ID: ") + chalk_source.bold(anvilUrl));
|
|
51175
51357
|
}
|
|
51176
|
-
|
|
51177
|
-
|
|
51178
|
-
|
|
51179
|
-
|
|
51180
|
-
|
|
51181
|
-
|
|
51182
|
-
|
|
51183
|
-
|
|
51184
|
-
|
|
51185
|
-
|
|
51186
|
-
|
|
51187
|
-
|
|
51188
|
-
|
|
51189
|
-
|
|
51190
|
-
|
|
51191
|
-
|
|
51192
|
-
|
|
51193
|
-
|
|
51194
|
-
|
|
51195
|
-
|
|
51196
|
-
|
|
51197
|
-
const browserName = ids[browser.id];
|
|
51198
|
-
if ('browserPrivate' === app) appArguments.push(flags[browserName]);
|
|
51199
|
-
return baseOpen({
|
|
51200
|
-
...options,
|
|
51201
|
-
app: {
|
|
51202
|
-
name: open_apps[browserName],
|
|
51203
|
-
arguments: appArguments
|
|
51358
|
+
if (binding.username && !explicitUsername) {
|
|
51359
|
+
username = binding.username;
|
|
51360
|
+
logger_logger.verbose(chalk_source.cyan("Resolved username from binding for app ID: ") + chalk_source.bold(username));
|
|
51361
|
+
}
|
|
51362
|
+
const remoteInfo = lookupRemoteInfoForAppId(explicitAppId, detectedFromAllRemotes);
|
|
51363
|
+
if (remoteInfo.detectedUrl && !explicitUrl && !anvilUrl) {
|
|
51364
|
+
anvilUrl = normalizeAnvilUrl(remoteInfo.detectedUrl);
|
|
51365
|
+
logger_logger.verbose(chalk_source.cyan("Resolved URL from remote for app ID: ") + chalk_source.bold(anvilUrl));
|
|
51366
|
+
}
|
|
51367
|
+
if (remoteInfo.detectedUsername && !explicitUsername && !username) {
|
|
51368
|
+
username = remoteInfo.detectedUsername;
|
|
51369
|
+
logger_logger.verbose(chalk_source.cyan("Resolved username from remote for app ID: ") + chalk_source.bold(username));
|
|
51370
|
+
}
|
|
51371
|
+
} else {
|
|
51372
|
+
logger_logger.verbose(chalk_source.cyan("No app ID provided, attempting auto-detection..."));
|
|
51373
|
+
if (0 === filteredCandidates.length) {
|
|
51374
|
+
logger_logger.verbose(chalk_source.gray("No app IDs found in git remotes."));
|
|
51375
|
+
const resolvedFallbackUrl = await resolveUrlForFallback(explicitUrl);
|
|
51376
|
+
if (null === resolvedFallbackUrl) {
|
|
51377
|
+
logger_logger.warn("Operation cancelled.");
|
|
51378
|
+
process.exit(0);
|
|
51204
51379
|
}
|
|
51205
|
-
|
|
51380
|
+
fallbackUrl = normalizeAnvilUrl(resolvedFallbackUrl);
|
|
51381
|
+
const lookupDecision = await confirmReverseLookupWithResolvedUser(fallbackUrl, username);
|
|
51382
|
+
if (null === lookupDecision) {
|
|
51383
|
+
logger_logger.warn("Operation cancelled.");
|
|
51384
|
+
process.exit(0);
|
|
51385
|
+
}
|
|
51386
|
+
username = lookupDecision.username;
|
|
51387
|
+
if (lookupDecision.shouldContinue) {
|
|
51388
|
+
logger_logger.progress("detect", `Searching ${fallbackUrl} ${username ? `for ${username}` : ""} for matching app IDs...`);
|
|
51389
|
+
const reverseLookupCandidates = await detectAppIdsByCommitLookup(repoPath, {
|
|
51390
|
+
anvilUrl: fallbackUrl,
|
|
51391
|
+
username,
|
|
51392
|
+
includeRemotes: false
|
|
51393
|
+
});
|
|
51394
|
+
logger_logger.progressEnd("detect");
|
|
51395
|
+
for (const c of reverseLookupCandidates)filteredCandidates.push({
|
|
51396
|
+
...c,
|
|
51397
|
+
detectedUrl: fallbackUrl
|
|
51398
|
+
});
|
|
51399
|
+
}
|
|
51400
|
+
}
|
|
51401
|
+
if (filteredCandidates.length > 0) {
|
|
51402
|
+
for (const c of filteredCandidates)logger_logger.verbose(chalk_source.gray(` Found: ${formatCandidateLabel(c)}`));
|
|
51403
|
+
if (filteredCandidates.length > 1) logger_logger.verbose(chalk_source.yellow(`Found ${filteredCandidates.length} potential app IDs`));
|
|
51404
|
+
}
|
|
51405
|
+
if (useFirst && filteredCandidates.length > 0) {
|
|
51406
|
+
const selected = filteredCandidates[0];
|
|
51407
|
+
finalAppId = selected.appId;
|
|
51408
|
+
if (selected.detectedUrl) anvilUrl = normalizeAnvilUrl(selected.detectedUrl);
|
|
51409
|
+
if (selected.detectedUsername && !username) username = selected.detectedUsername;
|
|
51410
|
+
logger_logger.success("Auto-selected first app ID: " + chalk_source.bold(finalAppId));
|
|
51411
|
+
} else {
|
|
51412
|
+
const selected = await selectAppId(filteredCandidates);
|
|
51413
|
+
if (!selected) {
|
|
51414
|
+
logger_logger.error("No app ID provided. Cannot continue without an app ID.");
|
|
51415
|
+
process.exit(1);
|
|
51416
|
+
}
|
|
51417
|
+
finalAppId = selected.appId;
|
|
51418
|
+
if (selected.detectedUrl) anvilUrl = normalizeAnvilUrl(selected.detectedUrl);
|
|
51419
|
+
if (selected.detectedUsername && !username) username = selected.detectedUsername;
|
|
51420
|
+
}
|
|
51206
51421
|
}
|
|
51207
|
-
|
|
51208
|
-
|
|
51209
|
-
|
|
51210
|
-
|
|
51211
|
-
|
|
51212
|
-
|
|
51213
|
-
|
|
51214
|
-
|
|
51215
|
-
|
|
51216
|
-
|
|
51217
|
-
if (
|
|
51218
|
-
|
|
51219
|
-
if (app) command = app;
|
|
51422
|
+
const binding = await getAppAuthBinding(repoPath, finalAppId);
|
|
51423
|
+
if (binding.url && !explicitUrl) {
|
|
51424
|
+
anvilUrl = normalizeAnvilUrl(binding.url);
|
|
51425
|
+
logger_logger.verbose(chalk_source.cyan("Using app binding URL: ") + chalk_source.bold(anvilUrl));
|
|
51426
|
+
}
|
|
51427
|
+
if (binding.username && !explicitUsername) {
|
|
51428
|
+
username = binding.username;
|
|
51429
|
+
logger_logger.verbose(chalk_source.cyan("Using app binding username: ") + chalk_source.bold(username));
|
|
51430
|
+
}
|
|
51431
|
+
shouldPersistUsernameBinding = !binding.username && !explicitUsername;
|
|
51432
|
+
if (explicitUrl) anvilUrl = normalizeAnvilUrl(explicitUrl);
|
|
51433
|
+
else if (!anvilUrl) if (fallbackUrl) anvilUrl = fallbackUrl;
|
|
51220
51434
|
else {
|
|
51221
|
-
const
|
|
51222
|
-
|
|
51223
|
-
|
|
51224
|
-
|
|
51225
|
-
|
|
51226
|
-
|
|
51227
|
-
const useSystemXdgOpen = external_node_process_.versions.electron ?? ('android' === platform || isBundled || !exeLocalXdgOpen);
|
|
51228
|
-
command = useSystemXdgOpen ? 'xdg-open' : localXdgOpenPath;
|
|
51435
|
+
const resolvedFallbackUrl = await resolveUrlForFallback();
|
|
51436
|
+
if (null === resolvedFallbackUrl) {
|
|
51437
|
+
logger_logger.warn("Operation cancelled.");
|
|
51438
|
+
process.exit(0);
|
|
51439
|
+
}
|
|
51440
|
+
anvilUrl = normalizeAnvilUrl(resolvedFallbackUrl);
|
|
51229
51441
|
}
|
|
51230
|
-
|
|
51231
|
-
|
|
51232
|
-
|
|
51233
|
-
|
|
51442
|
+
anvilUrl = normalizeAnvilUrl(anvilUrl);
|
|
51443
|
+
logger_logger.verbose(chalk_source.green("Using app ID: ") + chalk_source.bold(finalAppId));
|
|
51444
|
+
logger_logger.verbose(chalk_source.cyan("Using Anvil URL: ") + chalk_source.bold(anvilUrl));
|
|
51445
|
+
const resolvedUsername = await resolveUsernameForUrl(anvilUrl, username);
|
|
51446
|
+
if (null === resolvedUsername) {
|
|
51447
|
+
logger_logger.warn("Operation cancelled.");
|
|
51448
|
+
process.exit(0);
|
|
51234
51449
|
}
|
|
51235
|
-
|
|
51236
|
-
|
|
51237
|
-
|
|
51238
|
-
|
|
51239
|
-
|
|
51240
|
-
|
|
51241
|
-
|
|
51242
|
-
if (options.wait) encodedArguments.push('-Wait');
|
|
51243
|
-
if (app) {
|
|
51244
|
-
encodedArguments.push(`"\`"${app}\`""`);
|
|
51245
|
-
if (options.target) appArguments.push(options.target);
|
|
51246
|
-
} else if (options.target) encodedArguments.push(`"${options.target}"`);
|
|
51247
|
-
if (appArguments.length > 0) {
|
|
51248
|
-
appArguments = appArguments.map((argument)=>`"\`"${argument}\`""`);
|
|
51249
|
-
encodedArguments.push('-ArgumentList', appArguments.join(','));
|
|
51450
|
+
username = resolvedUsername;
|
|
51451
|
+
if (shouldPersistUsernameBinding && username && auth_getAccountsForUrl(anvilUrl).length > 1) {
|
|
51452
|
+
await setAppAuthBinding(repoPath, finalAppId, {
|
|
51453
|
+
url: anvilUrl,
|
|
51454
|
+
username
|
|
51455
|
+
});
|
|
51456
|
+
logger_logger.verbose(chalk_source.cyan("Saved app account binding for future non-interactive use."));
|
|
51250
51457
|
}
|
|
51251
|
-
|
|
51458
|
+
if (username) logger_logger.verbose(chalk_source.cyan("Using account: ") + chalk_source.bold(username));
|
|
51459
|
+
if (!hasTokensForUrl(anvilUrl, username)) {
|
|
51460
|
+
if (username) logger_logger.error(`Not logged in to ${anvilUrl} as ${username}`);
|
|
51461
|
+
else logger_logger.error(`Not logged in to ${anvilUrl}`);
|
|
51462
|
+
logger_logger.verbose(chalk_source.yellow("Please log in first:"));
|
|
51463
|
+
console.log(chalk_source.cyan(` anvil login ${anvilUrl.replace(/^https?:\/\//, "")}`));
|
|
51464
|
+
process.exit(1);
|
|
51465
|
+
}
|
|
51466
|
+
logger_logger.verbose(chalk_source.green("✓ Authentication tokens found"));
|
|
51467
|
+
logger_logger.progress("validate", `Validating app ID: ${finalAppId}`);
|
|
51468
|
+
const appIdValidation = await validateAppId(finalAppId, anvilUrl, username);
|
|
51469
|
+
logger_logger.progressEnd("validate");
|
|
51470
|
+
if (!appIdValidation.valid) {
|
|
51471
|
+
logger_logger.error(`App ID validation failed: ${appIdValidation.error}`);
|
|
51472
|
+
logger_logger.verbose(chalk_source.yellow("This could mean:"));
|
|
51473
|
+
logger_logger.verbose(chalk_source.yellow(" • The app ID doesn't exist on the server"));
|
|
51474
|
+
logger_logger.verbose(chalk_source.yellow(" • You don't have access to this app"));
|
|
51475
|
+
logger_logger.verbose(chalk_source.yellow(" • There's a network or authentication issue"));
|
|
51476
|
+
process.exit(1);
|
|
51477
|
+
}
|
|
51478
|
+
logger_logger.verbose(chalk_source.green(`✔ App ID validated successfully`));
|
|
51479
|
+
if (appIdValidation.app_name) logger_logger.verbose(chalk_source.gray(` App name: ${appIdValidation.app_name}`));
|
|
51480
|
+
if (stagedOnly) logger_logger.info(chalk_source.yellow("▸ Staged-only mode: Only staged changes will be synced"));
|
|
51481
|
+
if (autoMode) logger_logger.info(chalk_source.cyan("▸ Auto mode: Will automatically restart on branch changes and sync when behind"));
|
|
51482
|
+
logger_logger.progress("init", "Initializing watch session...");
|
|
51483
|
+
const session = await api_watch(repoPath, finalAppId, anvilUrl, stagedOnly, username);
|
|
51484
|
+
logger_logger.progressEnd("init");
|
|
51485
|
+
if (openAfterValidation) await openWatchPath(resolveWatchOpenPath(repoPath));
|
|
51486
|
+
logger_logger.verbose(chalk_source.blue("Watching for file changes..."));
|
|
51487
|
+
const started = await checkSyncStatusAndStart(session, {
|
|
51488
|
+
autoMode,
|
|
51489
|
+
repoPath,
|
|
51490
|
+
appId: finalAppId,
|
|
51491
|
+
anvilUrl,
|
|
51492
|
+
stagedOnly,
|
|
51493
|
+
username
|
|
51494
|
+
});
|
|
51495
|
+
if (!started) process.exit(1);
|
|
51496
|
+
} catch (e) {
|
|
51497
|
+
logger_logger.error("Error: " + errors_getErrorMessage(e));
|
|
51498
|
+
process.exit(1);
|
|
51252
51499
|
}
|
|
51253
|
-
|
|
51254
|
-
|
|
51255
|
-
const
|
|
51256
|
-
|
|
51257
|
-
|
|
51258
|
-
|
|
51259
|
-
|
|
51260
|
-
|
|
51500
|
+
}
|
|
51501
|
+
function registerWatchCommand(program) {
|
|
51502
|
+
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("-O, --open", "Open watched path in preferred editor (or default app)").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)=>{
|
|
51503
|
+
if (void 0 !== options.verbose && logger_logger instanceof CLILogger) logger_logger.setVerbose(options.verbose);
|
|
51504
|
+
await handleWatchCommand({
|
|
51505
|
+
path,
|
|
51506
|
+
appid: options.appid,
|
|
51507
|
+
useFirst: options.first,
|
|
51508
|
+
stagedOnly: options.stagedOnly,
|
|
51509
|
+
autoMode: options.auto,
|
|
51510
|
+
verbose: options.verbose,
|
|
51511
|
+
open: options.open,
|
|
51512
|
+
url: options.url,
|
|
51513
|
+
user: options.user
|
|
51261
51514
|
});
|
|
51262
51515
|
});
|
|
51263
|
-
|
|
51264
|
-
return subprocess;
|
|
51265
|
-
};
|
|
51266
|
-
const open_open = (target, options)=>{
|
|
51267
|
-
if ('string' != typeof target) throw new TypeError('Expected a `target`');
|
|
51268
|
-
return baseOpen({
|
|
51269
|
-
...options,
|
|
51270
|
-
target
|
|
51271
|
-
});
|
|
51272
|
-
};
|
|
51273
|
-
function detectArchBinary(binary) {
|
|
51274
|
-
if ('string' == typeof binary || Array.isArray(binary)) return binary;
|
|
51275
|
-
const { [arch]: archBinary } = binary;
|
|
51276
|
-
if (!archBinary) throw new Error(`${arch} is not supported`);
|
|
51277
|
-
return archBinary;
|
|
51278
|
-
}
|
|
51279
|
-
function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
|
|
51280
|
-
if (wsl && is_wsl) return detectArchBinary(wsl);
|
|
51281
|
-
if (!platformBinary) throw new Error(`${platform} is not supported`);
|
|
51282
|
-
return detectArchBinary(platformBinary);
|
|
51516
|
+
return watchCommand;
|
|
51283
51517
|
}
|
|
51284
|
-
const open_apps = {};
|
|
51285
|
-
defineLazyProperty(open_apps, 'chrome', ()=>detectPlatformBinary({
|
|
51286
|
-
darwin: 'google chrome',
|
|
51287
|
-
win32: 'chrome',
|
|
51288
|
-
linux: [
|
|
51289
|
-
'google-chrome',
|
|
51290
|
-
'google-chrome-stable',
|
|
51291
|
-
'chromium'
|
|
51292
|
-
]
|
|
51293
|
-
}, {
|
|
51294
|
-
wsl: {
|
|
51295
|
-
ia32: '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe',
|
|
51296
|
-
x64: [
|
|
51297
|
-
'/mnt/c/Program Files/Google/Chrome/Application/chrome.exe',
|
|
51298
|
-
'/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'
|
|
51299
|
-
]
|
|
51300
|
-
}
|
|
51301
|
-
}));
|
|
51302
|
-
defineLazyProperty(open_apps, 'brave', ()=>detectPlatformBinary({
|
|
51303
|
-
darwin: 'brave browser',
|
|
51304
|
-
win32: 'brave',
|
|
51305
|
-
linux: [
|
|
51306
|
-
'brave-browser',
|
|
51307
|
-
'brave'
|
|
51308
|
-
]
|
|
51309
|
-
}, {
|
|
51310
|
-
wsl: {
|
|
51311
|
-
ia32: '/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe',
|
|
51312
|
-
x64: [
|
|
51313
|
-
'/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe',
|
|
51314
|
-
'/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe'
|
|
51315
|
-
]
|
|
51316
|
-
}
|
|
51317
|
-
}));
|
|
51318
|
-
defineLazyProperty(open_apps, 'firefox', ()=>detectPlatformBinary({
|
|
51319
|
-
darwin: 'firefox',
|
|
51320
|
-
win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
|
|
51321
|
-
linux: 'firefox'
|
|
51322
|
-
}, {
|
|
51323
|
-
wsl: '/mnt/c/Program Files/Mozilla Firefox/firefox.exe'
|
|
51324
|
-
}));
|
|
51325
|
-
defineLazyProperty(open_apps, 'edge', ()=>detectPlatformBinary({
|
|
51326
|
-
darwin: 'microsoft edge',
|
|
51327
|
-
win32: 'msedge',
|
|
51328
|
-
linux: [
|
|
51329
|
-
'microsoft-edge',
|
|
51330
|
-
'microsoft-edge-dev'
|
|
51331
|
-
]
|
|
51332
|
-
}, {
|
|
51333
|
-
wsl: '/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'
|
|
51334
|
-
}));
|
|
51335
|
-
defineLazyProperty(open_apps, 'browser', ()=>'browser');
|
|
51336
|
-
defineLazyProperty(open_apps, 'browserPrivate', ()=>'browserPrivate');
|
|
51337
|
-
const node_modules_open = open_open;
|
|
51338
51518
|
var external_http_ = __webpack_require__("http");
|
|
51339
51519
|
const successPage = `<!DOCTYPE html>
|
|
51340
51520
|
<html lang="en">
|
|
@@ -51599,9 +51779,451 @@ var __webpack_exports__ = {};
|
|
|
51599
51779
|
scope: tokenData.scope
|
|
51600
51780
|
});
|
|
51601
51781
|
}
|
|
51782
|
+
const CHECKOUT_ERROR_VALUE = "__ERROR__";
|
|
51783
|
+
function isAbortLikeError(error) {
|
|
51784
|
+
if (error instanceof Error && "AbortError" === error.name) return true;
|
|
51785
|
+
if ("object" == typeof error && null !== error) {
|
|
51786
|
+
const maybeType = error.type;
|
|
51787
|
+
const maybeMessage = error.message;
|
|
51788
|
+
if ("network_error" === maybeType && "string" == typeof maybeMessage && maybeMessage.toLowerCase().includes("abort")) return true;
|
|
51789
|
+
}
|
|
51790
|
+
const message = errors_getErrorMessage(error).toLowerCase();
|
|
51791
|
+
return "aborted" === message || message.includes("aborted");
|
|
51792
|
+
}
|
|
51793
|
+
function normalizePickerQuery(term) {
|
|
51794
|
+
return (term || "").trim();
|
|
51795
|
+
}
|
|
51796
|
+
function getCheckoutPickerDelayMs(anvilUrl) {
|
|
51797
|
+
const raw = process.env.ANVIL_CHECKOUT_PICKER_DELAY_MS;
|
|
51798
|
+
const fromEnv = null == raw ? NaN : Number(raw);
|
|
51799
|
+
if (null != raw && Number.isFinite(fromEnv) && fromEnv >= 0) return fromEnv;
|
|
51800
|
+
return /localhost|127\.0\.0\.1/.test(anvilUrl) ? 250 : 0;
|
|
51801
|
+
}
|
|
51802
|
+
function getCheckoutPickerPaginationDelayMs(anvilUrl) {
|
|
51803
|
+
const raw = process.env.ANVIL_CHECKOUT_PICKER_PAGINATION_DELAY_MS;
|
|
51804
|
+
const fromEnv = null == raw ? NaN : Number(raw);
|
|
51805
|
+
if (null != raw && Number.isFinite(fromEnv) && fromEnv >= 0) return fromEnv;
|
|
51806
|
+
return /localhost|127\.0\.0\.1/.test(anvilUrl) ? 1000 : 0;
|
|
51807
|
+
}
|
|
51808
|
+
function getCheckoutPickerMaxRows() {
|
|
51809
|
+
const raw = process.env.ANVIL_CHECKOUT_PICKER_MAX_ROWS;
|
|
51810
|
+
const fromEnv = null == raw ? NaN : Number(raw);
|
|
51811
|
+
if (null != raw && Number.isFinite(fromEnv) && fromEnv >= 4) return Math.floor(fromEnv);
|
|
51812
|
+
return 12;
|
|
51813
|
+
}
|
|
51814
|
+
function formatLastEdited(lastEdited) {
|
|
51815
|
+
if (!lastEdited) return;
|
|
51816
|
+
return chalk_source.gray(`Last edited: ${lastEdited}`);
|
|
51817
|
+
}
|
|
51818
|
+
function formatAppPickerLabel(app) {
|
|
51819
|
+
const appName = app.app_name || "Unnamed App";
|
|
51820
|
+
return `${chalk_source.cyan(appName)} ${chalk_source.gray(`(${app.app_id})`)}`;
|
|
51821
|
+
}
|
|
51822
|
+
async function waitForDebounce(ms, signal) {
|
|
51823
|
+
if (ms <= 0) return;
|
|
51824
|
+
if (signal.aborted) throw new Error("aborted");
|
|
51825
|
+
await new Promise((resolve, reject)=>{
|
|
51826
|
+
const timer = setTimeout(()=>{
|
|
51827
|
+
cleanup();
|
|
51828
|
+
resolve();
|
|
51829
|
+
}, ms);
|
|
51830
|
+
const onAbort = ()=>{
|
|
51831
|
+
cleanup();
|
|
51832
|
+
reject(new Error("aborted"));
|
|
51833
|
+
};
|
|
51834
|
+
const cleanup = ()=>{
|
|
51835
|
+
clearTimeout(timer);
|
|
51836
|
+
signal.removeEventListener("abort", onAbort);
|
|
51837
|
+
};
|
|
51838
|
+
signal.addEventListener("abort", onAbort, {
|
|
51839
|
+
once: true
|
|
51840
|
+
});
|
|
51841
|
+
});
|
|
51842
|
+
}
|
|
51843
|
+
function createCheckoutPickerSource(anvilUrl, username, deps, options = {}) {
|
|
51844
|
+
const pageSize = options.pageSize ?? 20;
|
|
51845
|
+
const debounceMs = options.debounceMs ?? 200;
|
|
51846
|
+
const staleTimeMs = options.staleTimeMs ?? 30000;
|
|
51847
|
+
const maxAutoPagesPerCall = options.maxAutoPagesPerCall ?? 8;
|
|
51848
|
+
const initialQuery = normalizePickerQuery(options.initialQuery);
|
|
51849
|
+
const simulatedDelayMs = getCheckoutPickerDelayMs(anvilUrl);
|
|
51850
|
+
const paginationDelayMs = getCheckoutPickerPaginationDelayMs(anvilUrl);
|
|
51851
|
+
const cache = new Map();
|
|
51852
|
+
const getState = (query)=>{
|
|
51853
|
+
const existing = cache.get(query);
|
|
51854
|
+
if (existing) return existing;
|
|
51855
|
+
const created = {
|
|
51856
|
+
items: [],
|
|
51857
|
+
nextCursor: null,
|
|
51858
|
+
exhausted: false,
|
|
51859
|
+
lastError: null,
|
|
51860
|
+
updatedAt: 0,
|
|
51861
|
+
inFlight: null
|
|
51862
|
+
};
|
|
51863
|
+
cache.set(query, created);
|
|
51864
|
+
return created;
|
|
51865
|
+
};
|
|
51866
|
+
const fetchPage = async (query, signal, options = {})=>{
|
|
51867
|
+
const state = getState(query);
|
|
51868
|
+
if (state.inFlight) return void await state.inFlight;
|
|
51869
|
+
state.inFlight = (async ()=>{
|
|
51870
|
+
try {
|
|
51871
|
+
if (simulatedDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, simulatedDelayMs));
|
|
51872
|
+
if (options.cursor && paginationDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, paginationDelayMs));
|
|
51873
|
+
const response = await deps.listAppsForCheckout({
|
|
51874
|
+
anvilUrl,
|
|
51875
|
+
username,
|
|
51876
|
+
limit: pageSize,
|
|
51877
|
+
cursor: options.cursor,
|
|
51878
|
+
q: query || void 0,
|
|
51879
|
+
signal
|
|
51880
|
+
});
|
|
51881
|
+
if (options.reset) state.items = [
|
|
51882
|
+
...response.apps
|
|
51883
|
+
];
|
|
51884
|
+
else state.items.push(...response.apps);
|
|
51885
|
+
state.nextCursor = response.next_cursor;
|
|
51886
|
+
state.exhausted = !response.next_cursor;
|
|
51887
|
+
state.lastError = null;
|
|
51888
|
+
state.updatedAt = Date.now();
|
|
51889
|
+
} catch (e) {
|
|
51890
|
+
if (!signal.aborted && !isAbortLikeError(e)) {
|
|
51891
|
+
const message = errors_getErrorMessage(e);
|
|
51892
|
+
state.lastError = message;
|
|
51893
|
+
state.updatedAt = Date.now();
|
|
51894
|
+
}
|
|
51895
|
+
} finally{
|
|
51896
|
+
state.inFlight = null;
|
|
51897
|
+
}
|
|
51898
|
+
})();
|
|
51899
|
+
await state.inFlight;
|
|
51900
|
+
};
|
|
51901
|
+
const ensureLoaded = async (query, signal)=>{
|
|
51902
|
+
const state = getState(query);
|
|
51903
|
+
const isStale = Date.now() - state.updatedAt > staleTimeMs;
|
|
51904
|
+
if (0 === state.items.length) {
|
|
51905
|
+
await waitForDebounce(debounceMs, signal);
|
|
51906
|
+
await fetchPage(query, signal, {
|
|
51907
|
+
cursor: void 0,
|
|
51908
|
+
reset: false
|
|
51909
|
+
});
|
|
51910
|
+
} else if (state.lastError) {
|
|
51911
|
+
await waitForDebounce(debounceMs, signal);
|
|
51912
|
+
await fetchPage(query, signal, {
|
|
51913
|
+
cursor: void 0,
|
|
51914
|
+
reset: true
|
|
51915
|
+
});
|
|
51916
|
+
} else if (isStale) {
|
|
51917
|
+
await waitForDebounce(debounceMs, signal);
|
|
51918
|
+
await fetchPage(query, signal, {
|
|
51919
|
+
cursor: void 0,
|
|
51920
|
+
reset: true
|
|
51921
|
+
});
|
|
51922
|
+
}
|
|
51923
|
+
let pagesLoaded = 0;
|
|
51924
|
+
while(state.nextCursor && pagesLoaded < maxAutoPagesPerCall){
|
|
51925
|
+
if (signal.aborted) throw new Error("aborted");
|
|
51926
|
+
const cursor = state.nextCursor;
|
|
51927
|
+
await fetchPage(query, signal, {
|
|
51928
|
+
cursor,
|
|
51929
|
+
reset: false
|
|
51930
|
+
});
|
|
51931
|
+
pagesLoaded += 1;
|
|
51932
|
+
}
|
|
51933
|
+
};
|
|
51934
|
+
return {
|
|
51935
|
+
source: async (term, { signal })=>{
|
|
51936
|
+
const query = normalizePickerQuery(term) || initialQuery;
|
|
51937
|
+
if (signal.aborted) return [];
|
|
51938
|
+
await ensureLoaded(query, signal);
|
|
51939
|
+
const state = getState(query);
|
|
51940
|
+
if (state.lastError) return [
|
|
51941
|
+
{
|
|
51942
|
+
name: `${chalk_source.yellow("Fetch failed")} ${chalk_source.gray(`(${state.lastError})`)}`,
|
|
51943
|
+
value: CHECKOUT_ERROR_VALUE,
|
|
51944
|
+
disabled: true
|
|
51945
|
+
}
|
|
51946
|
+
];
|
|
51947
|
+
const summary = state.nextCursor ? chalk_source.gray(`Loaded ${state.items.length} apps • more available`) : chalk_source.gray(`Loaded ${state.items.length} apps`);
|
|
51948
|
+
const choices = state.items.map((app)=>({
|
|
51949
|
+
name: formatAppPickerLabel(app),
|
|
51950
|
+
value: app.app_id,
|
|
51951
|
+
description: formatLastEdited(app.last_edited)
|
|
51952
|
+
}));
|
|
51953
|
+
choices.unshift({
|
|
51954
|
+
name: summary,
|
|
51955
|
+
value: CHECKOUT_ERROR_VALUE,
|
|
51956
|
+
disabled: true
|
|
51957
|
+
});
|
|
51958
|
+
return choices;
|
|
51959
|
+
}
|
|
51960
|
+
};
|
|
51961
|
+
}
|
|
51962
|
+
const INLINE_SPINNER_FRAMES = [
|
|
51963
|
+
"⠋",
|
|
51964
|
+
"⠙",
|
|
51965
|
+
"⠹",
|
|
51966
|
+
"⠸",
|
|
51967
|
+
"⠼",
|
|
51968
|
+
"⠴",
|
|
51969
|
+
"⠦",
|
|
51970
|
+
"⠧",
|
|
51971
|
+
"⠇",
|
|
51972
|
+
"⠏"
|
|
51973
|
+
];
|
|
51974
|
+
async function runCustomCheckoutPicker(anvilUrl, username, deps, initialQuery) {
|
|
51975
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
|
|
51976
|
+
const pageSize = 20;
|
|
51977
|
+
const staleTimeMs = 30000;
|
|
51978
|
+
const debounceMs = 180;
|
|
51979
|
+
const simulatedDelayMs = getCheckoutPickerDelayMs(anvilUrl);
|
|
51980
|
+
const paginationDelayMs = getCheckoutPickerPaginationDelayMs(anvilUrl);
|
|
51981
|
+
const maxVisibleRows = getCheckoutPickerMaxRows();
|
|
51982
|
+
const cache = new Map();
|
|
51983
|
+
let query = normalizePickerQuery(initialQuery);
|
|
51984
|
+
let selectedIndex = 0;
|
|
51985
|
+
let scrollOffset = 0;
|
|
51986
|
+
let loading = false;
|
|
51987
|
+
let loadingMore = false;
|
|
51988
|
+
let done = false;
|
|
51989
|
+
let pendingTimer = null;
|
|
51990
|
+
let loadingRenderTimer = null;
|
|
51991
|
+
let activeController = null;
|
|
51992
|
+
let resolveResult = null;
|
|
51993
|
+
const ensureState = (key)=>{
|
|
51994
|
+
const existing = cache.get(key);
|
|
51995
|
+
if (existing) return existing;
|
|
51996
|
+
const created = {
|
|
51997
|
+
items: [],
|
|
51998
|
+
nextCursor: null,
|
|
51999
|
+
lastError: null,
|
|
52000
|
+
updatedAt: 0
|
|
52001
|
+
};
|
|
52002
|
+
cache.set(key, created);
|
|
52003
|
+
return created;
|
|
52004
|
+
};
|
|
52005
|
+
const currentState = ()=>ensureState(query);
|
|
52006
|
+
const clearScreen = ()=>{
|
|
52007
|
+
process.stdout.write("\x1b[2J\x1b[H");
|
|
52008
|
+
};
|
|
52009
|
+
const visibleRows = ()=>{
|
|
52010
|
+
const rows = process.stdout.rows || 24;
|
|
52011
|
+
return Math.min(maxVisibleRows, Math.max(6, rows - 9));
|
|
52012
|
+
};
|
|
52013
|
+
const syncViewport = ()=>{
|
|
52014
|
+
const items = currentState().items;
|
|
52015
|
+
if (selectedIndex >= items.length) selectedIndex = Math.max(0, items.length - 1);
|
|
52016
|
+
const height = visibleRows();
|
|
52017
|
+
if (selectedIndex < scrollOffset) scrollOffset = selectedIndex;
|
|
52018
|
+
else if (selectedIndex >= scrollOffset + height) scrollOffset = Math.max(0, selectedIndex - height + 1);
|
|
52019
|
+
};
|
|
52020
|
+
const render = ()=>{
|
|
52021
|
+
clearScreen();
|
|
52022
|
+
const state = currentState();
|
|
52023
|
+
const items = state.items;
|
|
52024
|
+
const activeQuery = query || chalk_source.gray("(all apps)");
|
|
52025
|
+
const spinnerFrame = INLINE_SPINNER_FRAMES[Math.floor(Date.now() / 120) % INLINE_SPINNER_FRAMES.length];
|
|
52026
|
+
const status = loading ? loadingMore ? chalk_source.yellow(`${spinnerFrame} Loading more apps... (${items.length} loaded)`) : chalk_source.yellow(`${spinnerFrame} Loading apps...`) : state.nextCursor ? chalk_source.gray(`Loaded ${items.length} apps • more available`) : chalk_source.gray(`Loaded ${items.length} apps`);
|
|
52027
|
+
process.stdout.write(`${chalk_source.bold("Search apps by name or app ID")}\n`);
|
|
52028
|
+
process.stdout.write(`${chalk_source.cyan("Query:")} ${activeQuery}\n`);
|
|
52029
|
+
process.stdout.write(`${status}\n`);
|
|
52030
|
+
if (state.lastError) process.stdout.write(`${chalk_source.red(`Fetch failed: ${state.lastError}`)}\n`);
|
|
52031
|
+
const height = visibleRows();
|
|
52032
|
+
const start = scrollOffset;
|
|
52033
|
+
const end = Math.min(items.length, start + height);
|
|
52034
|
+
if (0 !== items.length || loading || state.lastError) for(let i = start; i < end; i += 1){
|
|
52035
|
+
const item = items[i];
|
|
52036
|
+
const label = formatAppPickerLabel(item);
|
|
52037
|
+
const line = i === selectedIndex ? `${chalk_source.green("❯")} ${label}` : ` ${label}`;
|
|
52038
|
+
process.stdout.write(`${line}\n`);
|
|
52039
|
+
}
|
|
52040
|
+
else process.stdout.write(`${chalk_source.gray("No matches. Keep typing.")}\n`);
|
|
52041
|
+
process.stdout.write(`\n${chalk_source.gray("↑/↓ navigate • type to search • enter select • esc/ctrl+c cancel")}\n`);
|
|
52042
|
+
};
|
|
52043
|
+
const fetchPage = async (key, cursor)=>{
|
|
52044
|
+
const state = ensureState(key);
|
|
52045
|
+
const controller = new AbortController();
|
|
52046
|
+
if (!cursor && activeController) activeController.abort();
|
|
52047
|
+
activeController = controller;
|
|
52048
|
+
loading = true;
|
|
52049
|
+
loadingMore = !!cursor;
|
|
52050
|
+
startLoadingAnimation();
|
|
52051
|
+
render();
|
|
52052
|
+
try {
|
|
52053
|
+
if (simulatedDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, simulatedDelayMs));
|
|
52054
|
+
if (cursor && paginationDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, paginationDelayMs));
|
|
52055
|
+
const response = await deps.listAppsForCheckout({
|
|
52056
|
+
anvilUrl,
|
|
52057
|
+
username,
|
|
52058
|
+
limit: pageSize,
|
|
52059
|
+
cursor,
|
|
52060
|
+
q: key || void 0,
|
|
52061
|
+
signal: controller.signal
|
|
52062
|
+
});
|
|
52063
|
+
const merged = cursor ? state.items.concat(response.apps) : response.apps;
|
|
52064
|
+
cache.set(key, {
|
|
52065
|
+
items: merged,
|
|
52066
|
+
nextCursor: response.next_cursor,
|
|
52067
|
+
lastError: null,
|
|
52068
|
+
updatedAt: Date.now()
|
|
52069
|
+
});
|
|
52070
|
+
if (key === query) syncViewport();
|
|
52071
|
+
} catch (e) {
|
|
52072
|
+
if (!controller.signal.aborted && !isAbortLikeError(e)) {
|
|
52073
|
+
const message = errors_getErrorMessage(e);
|
|
52074
|
+
cache.set(key, {
|
|
52075
|
+
...state,
|
|
52076
|
+
lastError: message,
|
|
52077
|
+
updatedAt: Date.now()
|
|
52078
|
+
});
|
|
52079
|
+
}
|
|
52080
|
+
} finally{
|
|
52081
|
+
if (activeController === controller) activeController = null;
|
|
52082
|
+
loading = false;
|
|
52083
|
+
loadingMore = false;
|
|
52084
|
+
stopLoadingAnimation();
|
|
52085
|
+
render();
|
|
52086
|
+
}
|
|
52087
|
+
};
|
|
52088
|
+
const ensureFresh = async (key)=>{
|
|
52089
|
+
const state = ensureState(key);
|
|
52090
|
+
const stale = Date.now() - state.updatedAt > staleTimeMs;
|
|
52091
|
+
if (0 === state.items.length || stale || state.lastError) await fetchPage(key);
|
|
52092
|
+
else render();
|
|
52093
|
+
};
|
|
52094
|
+
const maybeLoadMore = async ()=>{
|
|
52095
|
+
const state = currentState();
|
|
52096
|
+
if (!state.nextCursor || loading) return;
|
|
52097
|
+
if (selectedIndex >= Math.max(0, state.items.length - 2)) await fetchPage(query, state.nextCursor || void 0);
|
|
52098
|
+
};
|
|
52099
|
+
const scheduleQueryFetch = ()=>{
|
|
52100
|
+
if (pendingTimer) clearTimeout(pendingTimer);
|
|
52101
|
+
pendingTimer = setTimeout(()=>{
|
|
52102
|
+
pendingTimer = null;
|
|
52103
|
+
ensureFresh(query);
|
|
52104
|
+
}, debounceMs);
|
|
52105
|
+
};
|
|
52106
|
+
const startLoadingAnimation = ()=>{
|
|
52107
|
+
if (loadingRenderTimer) return;
|
|
52108
|
+
loadingRenderTimer = setInterval(()=>{
|
|
52109
|
+
if (!done && loading) render();
|
|
52110
|
+
}, 120);
|
|
52111
|
+
};
|
|
52112
|
+
const stopLoadingAnimation = ()=>{
|
|
52113
|
+
if (!loadingRenderTimer) return;
|
|
52114
|
+
clearInterval(loadingRenderTimer);
|
|
52115
|
+
loadingRenderTimer = null;
|
|
52116
|
+
};
|
|
52117
|
+
const finish = (value)=>{
|
|
52118
|
+
done = true;
|
|
52119
|
+
if (pendingTimer) {
|
|
52120
|
+
clearTimeout(pendingTimer);
|
|
52121
|
+
pendingTimer = null;
|
|
52122
|
+
}
|
|
52123
|
+
if (activeController) {
|
|
52124
|
+
activeController.abort();
|
|
52125
|
+
activeController = null;
|
|
52126
|
+
}
|
|
52127
|
+
stopLoadingAnimation();
|
|
52128
|
+
process.stdin.removeListener("keypress", onKeypress);
|
|
52129
|
+
if (process.stdin.isTTY && process.stdin.setRawMode) process.stdin.setRawMode(false);
|
|
52130
|
+
process.stdin.pause();
|
|
52131
|
+
clearScreen();
|
|
52132
|
+
if (resolveResult) resolveResult(value);
|
|
52133
|
+
};
|
|
52134
|
+
const onKeypress = (_str, key)=>{
|
|
52135
|
+
if (done) return;
|
|
52136
|
+
if (key.ctrl && "c" === key.name) return void finish(null);
|
|
52137
|
+
if ("escape" === key.name) return void finish(null);
|
|
52138
|
+
if ("return" === key.name) {
|
|
52139
|
+
const state = currentState();
|
|
52140
|
+
const selected = state.items[selectedIndex];
|
|
52141
|
+
finish(selected ? selected.app_id : null);
|
|
52142
|
+
return;
|
|
52143
|
+
}
|
|
52144
|
+
if ("up" === key.name) {
|
|
52145
|
+
if (selectedIndex > 0) {
|
|
52146
|
+
selectedIndex -= 1;
|
|
52147
|
+
syncViewport();
|
|
52148
|
+
render();
|
|
52149
|
+
}
|
|
52150
|
+
return;
|
|
52151
|
+
}
|
|
52152
|
+
if ("down" === key.name) {
|
|
52153
|
+
const maxIndex = Math.max(0, currentState().items.length - 1);
|
|
52154
|
+
if (selectedIndex < maxIndex) {
|
|
52155
|
+
selectedIndex += 1;
|
|
52156
|
+
syncViewport();
|
|
52157
|
+
render();
|
|
52158
|
+
maybeLoadMore();
|
|
52159
|
+
}
|
|
52160
|
+
return;
|
|
52161
|
+
}
|
|
52162
|
+
if ("backspace" === key.name || "delete" === key.name) {
|
|
52163
|
+
if (query.length > 0) {
|
|
52164
|
+
query = query.slice(0, -1);
|
|
52165
|
+
selectedIndex = 0;
|
|
52166
|
+
scrollOffset = 0;
|
|
52167
|
+
render();
|
|
52168
|
+
scheduleQueryFetch();
|
|
52169
|
+
}
|
|
52170
|
+
return;
|
|
52171
|
+
}
|
|
52172
|
+
if (!key.ctrl && !key.meta && key.sequence && 1 === key.sequence.length && key.sequence >= " ") {
|
|
52173
|
+
query += key.sequence;
|
|
52174
|
+
selectedIndex = 0;
|
|
52175
|
+
scrollOffset = 0;
|
|
52176
|
+
render();
|
|
52177
|
+
scheduleQueryFetch();
|
|
52178
|
+
}
|
|
52179
|
+
};
|
|
52180
|
+
logger_logger.pause();
|
|
52181
|
+
try {
|
|
52182
|
+
external_readline_default().emitKeypressEvents(process.stdin);
|
|
52183
|
+
if (process.stdin.isTTY && process.stdin.setRawMode) process.stdin.setRawMode(true);
|
|
52184
|
+
process.stdin.resume();
|
|
52185
|
+
process.stdin.on("keypress", onKeypress);
|
|
52186
|
+
await ensureFresh(query);
|
|
52187
|
+
return await new Promise((resolve)=>{
|
|
52188
|
+
resolveResult = resolve;
|
|
52189
|
+
});
|
|
52190
|
+
} finally{
|
|
52191
|
+
logger_logger.resume();
|
|
52192
|
+
}
|
|
52193
|
+
}
|
|
52194
|
+
async function selectAppForCheckout(anvilUrl, username, deps, initialQuery) {
|
|
52195
|
+
if (!isTestMode() && "1" !== process.env.ANVIL_CHECKOUT_LEGACY_PICKER) return runCustomCheckoutPicker(anvilUrl, username, deps, initialQuery);
|
|
52196
|
+
const picker = createCheckoutPickerSource(anvilUrl, username, deps, {
|
|
52197
|
+
initialQuery
|
|
52198
|
+
});
|
|
52199
|
+
try {
|
|
52200
|
+
const answer = await logger_logger.prompt([
|
|
52201
|
+
{
|
|
52202
|
+
type: "search",
|
|
52203
|
+
name: "value",
|
|
52204
|
+
message: "Search apps by name or app ID",
|
|
52205
|
+
source: picker.source,
|
|
52206
|
+
pageSize: 12,
|
|
52207
|
+
loop: false,
|
|
52208
|
+
instructions: {
|
|
52209
|
+
navigation: "↑↓ navigate • type to filter",
|
|
52210
|
+
pager: "enter select • ctrl+c cancel"
|
|
52211
|
+
}
|
|
52212
|
+
}
|
|
52213
|
+
]);
|
|
52214
|
+
const selected = String(answer.value || "");
|
|
52215
|
+
if (!selected || selected === CHECKOUT_ERROR_VALUE) return null;
|
|
52216
|
+
return selected;
|
|
52217
|
+
} catch (e) {
|
|
52218
|
+
const err = e;
|
|
52219
|
+
if ("ExitPromptError" === err.name || String(err.message || "").includes("User force closed")) return null;
|
|
52220
|
+
throw e;
|
|
52221
|
+
}
|
|
52222
|
+
}
|
|
51602
52223
|
const defaultCheckoutDeps = {
|
|
51603
52224
|
getValidAuthToken: auth_getValidAuthToken,
|
|
51604
52225
|
validateAppId: validateAppId,
|
|
52226
|
+
listAppsForCheckout: listAppsForCheckout,
|
|
51605
52227
|
runInteractiveLoginFlow: runInteractiveLoginFlow,
|
|
51606
52228
|
clone: async (repoUrl, destinationPath, options)=>{
|
|
51607
52229
|
const cloneArgs = [];
|
|
@@ -51615,6 +52237,9 @@ var __webpack_exports__ = {};
|
|
|
51615
52237
|
},
|
|
51616
52238
|
hardenCheckoutGitAuth: hardenCheckoutGitAuth
|
|
51617
52239
|
};
|
|
52240
|
+
function isInteractiveSession() {
|
|
52241
|
+
return !!(process.stdin.isTTY && process.stdout.isTTY);
|
|
52242
|
+
}
|
|
51618
52243
|
function parseCheckoutInput(input) {
|
|
51619
52244
|
const trimmed = input.trim();
|
|
51620
52245
|
if (!trimmed) throw new Error("Input is required.");
|
|
@@ -51737,10 +52362,25 @@ var __webpack_exports__ = {};
|
|
|
51737
52362
|
return logger_logger.select(`Multiple accounts found for ${anvilUrl}. Which account should be used for checkout?`, choices, accounts[0]);
|
|
51738
52363
|
}
|
|
51739
52364
|
async function executeCheckout(options, deps = defaultCheckoutDeps) {
|
|
51740
|
-
|
|
51741
|
-
|
|
52365
|
+
let checkoutInput = options.input?.trim();
|
|
52366
|
+
let preselectedAnvilUrl;
|
|
52367
|
+
let preselectedUsername;
|
|
52368
|
+
if (!checkoutInput) {
|
|
52369
|
+
if (!isInteractiveSession()) throw new Error("`anvil checkout` without arguments requires an interactive TTY. Pass APP_ID or URL explicitly in non-interactive mode.");
|
|
52370
|
+
const selectedUrl = await resolveCheckoutUrl(options.url);
|
|
52371
|
+
if (!selectedUrl) return void logger_logger.info("Checkout cancelled.");
|
|
52372
|
+
preselectedAnvilUrl = selectedUrl;
|
|
52373
|
+
const selectedUsername = await resolveCheckoutUsername(selectedUrl, options.user);
|
|
52374
|
+
if (null === selectedUsername) return void logger_logger.info("Checkout cancelled.");
|
|
52375
|
+
preselectedUsername = selectedUsername || void 0;
|
|
52376
|
+
const selectedInput = await selectAppForCheckout(selectedUrl, preselectedUsername, deps, options.query);
|
|
52377
|
+
if (!selectedInput) return void logger_logger.info("Checkout cancelled.");
|
|
52378
|
+
checkoutInput = selectedInput;
|
|
52379
|
+
}
|
|
52380
|
+
const parsed = parseCheckoutInput(checkoutInput);
|
|
52381
|
+
const anvilUrl = preselectedAnvilUrl || await resolveCheckoutUrl(options.url, parsed.detectedUrl);
|
|
51742
52382
|
if (!anvilUrl) return void logger_logger.info("Checkout cancelled.");
|
|
51743
|
-
const resolvedUsername = await resolveCheckoutUsername(anvilUrl, options.user);
|
|
52383
|
+
const resolvedUsername = preselectedUsername || await resolveCheckoutUsername(anvilUrl, options.user);
|
|
51744
52384
|
if (null === resolvedUsername) return void logger_logger.info("Checkout cancelled.");
|
|
51745
52385
|
const authToken = await ensureCheckoutAuthToken(anvilUrl, resolvedUsername, deps);
|
|
51746
52386
|
let checkoutUsername = resolvedUsername;
|
|
@@ -51782,30 +52422,18 @@ var __webpack_exports__ = {};
|
|
|
51782
52422
|
logger_logger.progressEnd("checkout", `Checked out ${parsed.appId} into ${destinationDisplay}`);
|
|
51783
52423
|
const preferredEditor = String(getConfig("preferredEditor") || "").trim();
|
|
51784
52424
|
const preferredEditorCommand = preferredEditor ? getPreferredEditorCommand(preferredEditor) : "";
|
|
51785
|
-
if (options.open)
|
|
51786
|
-
|
|
51787
|
-
await node_modules_open(destinationPath);
|
|
52425
|
+
if (options.open) {
|
|
52426
|
+
await checkout_openPathInEditorOrDefault(destinationPath, preferredEditorCommand);
|
|
51788
52427
|
logger_logger.info(chalk_source.gray(`Opened ${destinationDisplay}`));
|
|
51789
52428
|
}
|
|
51790
|
-
if (preferredEditorCommand && !options.open) logger_logger.info(chalk_source.cyan(`Next: ${preferredEditorCommand} ${destinationDisplay}`));
|
|
52429
|
+
if (preferredEditorCommand && !options.open) if (isCommandAvailable(preferredEditorCommand)) logger_logger.info(chalk_source.cyan(`Next: ${preferredEditorCommand} ${destinationDisplay}`));
|
|
52430
|
+
else logger_logger.warn(`Preferred editor command '${preferredEditorCommand}' was not found in PATH. Run 'anvil configure' to choose an installed editor.`);
|
|
51791
52431
|
}
|
|
51792
|
-
async function
|
|
51793
|
-
await
|
|
51794
|
-
const child = (0, external_child_process_.spawn)(editorCommand, [
|
|
51795
|
-
destinationPath
|
|
51796
|
-
], {
|
|
51797
|
-
shell: true,
|
|
51798
|
-
stdio: "inherit"
|
|
51799
|
-
});
|
|
51800
|
-
child.on("error", reject);
|
|
51801
|
-
child.on("exit", (code)=>{
|
|
51802
|
-
if (0 === code || null === code) resolve();
|
|
51803
|
-
else reject(new Error(`Editor command '${editorCommand}' exited with code ${code}`));
|
|
51804
|
-
});
|
|
51805
|
-
});
|
|
52432
|
+
async function checkout_openPathInEditorOrDefault(destinationPath, preferredEditorCommand, deps) {
|
|
52433
|
+
await openPathInEditorOrDefault(destinationPath, preferredEditorCommand, deps);
|
|
51806
52434
|
}
|
|
51807
52435
|
function registerCheckoutCommand(program) {
|
|
51808
|
-
const checkoutCommand = program.command("checkout
|
|
52436
|
+
const checkoutCommand = program.command("checkout [input] [directory]").description("Check out an Anvil app locally from editor URL, git URL, app ID, or interactive selection").alias("co").option("-O, --open", "Open destination after checkout").option("-b, --branch <BRANCH>", "Checkout a specific branch").option("--depth <N>", "Create a shallow clone with history truncated to N commits", (value)=>parseInt(value, 10)).option("--single-branch", "Clone only one branch").option("--origin <NAME>", "Use a custom remote name instead of origin").option("--quiet", "Suppress git clone progress output").option("--verbose", "Enable verbose git clone output").option("-u, --url <ANVIL_URL>", "Specify Anvil server URL").option("-U, --user <USERNAME>", "Specify which user account to use").option("-f, --force", "Override safety checks for destination path").option("-Q, --query <QUERY>", "Initial search query for interactive checkout picker").action(async (input, directory, options)=>{
|
|
51809
52437
|
try {
|
|
51810
52438
|
if ("number" == typeof options?.depth && (!Number.isFinite(options.depth) || options.depth <= 0)) throw new Error("--depth must be a positive integer");
|
|
51811
52439
|
await executeCheckout({
|
|
@@ -51820,16 +52448,17 @@ var __webpack_exports__ = {};
|
|
|
51820
52448
|
verbose: options?.verbose,
|
|
51821
52449
|
url: options?.url,
|
|
51822
52450
|
user: options?.user,
|
|
51823
|
-
force: options?.force
|
|
52451
|
+
force: options?.force,
|
|
52452
|
+
query: options?.query
|
|
51824
52453
|
}, defaultCheckoutDeps);
|
|
51825
52454
|
} catch (e) {
|
|
51826
52455
|
logger_logger.error("Error: " + errors_getErrorMessage(e));
|
|
51827
52456
|
process.exit(1);
|
|
51828
52457
|
}
|
|
51829
52458
|
});
|
|
51830
|
-
checkoutCommand.addHelpText("after", "\n" + chalk_source.bold("Examples:") +
|
|
52459
|
+
checkoutCommand.addHelpText("after", "\n" + chalk_source.bold("Examples:") + '\n anvil checkout http://localhost:3000/build/apps/APPID/code/assets/theme.css\n anvil checkout https://anvil.works/git/APPID.git\n anvil checkout APPID --url anvil.works\n anvil checkout APPID --branch master --depth 1 --single-branch\n anvil checkout APPID -O # open editor/file browser after checkout\n anvil checkout APPID my-local-folder --force\n anvil checkout # interactive search/select app list\n anvil checkout -Q "dashboard" # preseed picker search\n');
|
|
51831
52460
|
}
|
|
51832
|
-
const
|
|
52461
|
+
const gitCredential_defaultDeps = {
|
|
51833
52462
|
getValidAuthToken: auth_getValidAuthToken,
|
|
51834
52463
|
getAccountsForUrl: auth_getAccountsForUrl,
|
|
51835
52464
|
getAppAuthBinding: getAppAuthBinding,
|
|
@@ -51848,7 +52477,7 @@ var __webpack_exports__ = {};
|
|
|
51848
52477
|
}
|
|
51849
52478
|
return out;
|
|
51850
52479
|
}
|
|
51851
|
-
async function buildGitCredentialResponse(operation, request, deps =
|
|
52480
|
+
async function buildGitCredentialResponse(operation, request, deps = gitCredential_defaultDeps) {
|
|
51852
52481
|
if ("get" !== operation) return null;
|
|
51853
52482
|
if (!request.protocol || !request.host) return null;
|
|
51854
52483
|
const appId = parseAppIdFromGitPath(request.path);
|
|
@@ -51880,7 +52509,7 @@ var __webpack_exports__ = {};
|
|
|
51880
52509
|
for (const [k, v] of Object.entries(response))lines.push(`${k}=${v}`);
|
|
51881
52510
|
process.stdout.write(lines.join("\n") + "\n\n");
|
|
51882
52511
|
}
|
|
51883
|
-
async function executeGitCredentialOperation(operation, deps =
|
|
52512
|
+
async function executeGitCredentialOperation(operation, deps = gitCredential_defaultDeps) {
|
|
51884
52513
|
const raw = await readStdin();
|
|
51885
52514
|
const request = parseGitCredentialRequest(raw);
|
|
51886
52515
|
const response = await buildGitCredentialResponse(operation, request, deps);
|
|
@@ -52111,14 +52740,13 @@ var __webpack_exports__ = {};
|
|
|
52111
52740
|
console.log();
|
|
52112
52741
|
});
|
|
52113
52742
|
}
|
|
52114
|
-
const
|
|
52743
|
+
const configure_defaultDeps = {
|
|
52115
52744
|
getLatestVersion: getLatestVersion,
|
|
52116
52745
|
getAccountsForUrl: auth_getAccountsForUrl,
|
|
52117
|
-
runInteractiveLoginFlow: runInteractiveLoginFlow
|
|
52118
|
-
executeCheckout: executeCheckout
|
|
52746
|
+
runInteractiveLoginFlow: runInteractiveLoginFlow
|
|
52119
52747
|
};
|
|
52120
52748
|
const DEFAULT_ANVIL_SERVER_URL_PROMPT = "Default Anvil server URL";
|
|
52121
|
-
async function
|
|
52749
|
+
async function getConfigureVersionStatus(currentVersion, latestVersionGetter = getLatestVersion) {
|
|
52122
52750
|
const latestVersion = await latestVersionGetter();
|
|
52123
52751
|
if (!latestVersion) return {
|
|
52124
52752
|
currentVersion,
|
|
@@ -52141,25 +52769,25 @@ var __webpack_exports__ = {};
|
|
|
52141
52769
|
if (1 === accounts.length) return accounts[0];
|
|
52142
52770
|
return `${accounts.length} accounts`;
|
|
52143
52771
|
}
|
|
52144
|
-
function
|
|
52772
|
+
function configure_isInteractiveSession() {
|
|
52145
52773
|
return !!(process.stdin.isTTY && process.stdout.isTTY);
|
|
52146
52774
|
}
|
|
52147
|
-
async function
|
|
52148
|
-
if (!
|
|
52775
|
+
async function runConfigureFlow(version, deps = configure_defaultDeps) {
|
|
52776
|
+
if (!configure_isInteractiveSession()) throw new Error("`anvil configure` is interactive and requires a TTY terminal.");
|
|
52149
52777
|
console.log();
|
|
52150
|
-
logger_logger.info(chalk_source.cyan.bold("Anvil
|
|
52778
|
+
logger_logger.info(chalk_source.cyan.bold("Anvil Configuration"));
|
|
52151
52779
|
console.log();
|
|
52152
|
-
logger_logger.progress("
|
|
52153
|
-
const versionStatus = await
|
|
52154
|
-
logger_logger.progressEnd("
|
|
52780
|
+
logger_logger.progress("configure-version", "Checking CLI version...");
|
|
52781
|
+
const versionStatus = await getConfigureVersionStatus(version, deps.getLatestVersion);
|
|
52782
|
+
logger_logger.progressEnd("configure-version");
|
|
52155
52783
|
logger_logger.info(chalk_source.cyan("CLI version: ") + chalk_source.bold(versionStatus.currentVersion));
|
|
52156
52784
|
if (versionStatus.latestVersion) {
|
|
52157
52785
|
logger_logger.info(chalk_source.cyan("Latest version: ") + chalk_source.bold(versionStatus.latestVersion));
|
|
52158
52786
|
if (versionStatus.isOutdated) {
|
|
52159
52787
|
logger_logger.warn("Your anvil-cli is out of date.");
|
|
52160
52788
|
logger_logger.info(chalk_source.gray("Run `anvil update` to see update commands."));
|
|
52161
|
-
const continueOnOldVersion = await logger_logger.confirm("Continue
|
|
52162
|
-
if (!continueOnOldVersion) return void logger_logger.info("
|
|
52789
|
+
const continueOnOldVersion = await logger_logger.confirm("Continue configuration anyway?", true);
|
|
52790
|
+
if (!continueOnOldVersion) return void logger_logger.info("Configuration cancelled.");
|
|
52163
52791
|
}
|
|
52164
52792
|
} else logger_logger.warn("Could not determine latest published version.");
|
|
52165
52793
|
console.log();
|
|
@@ -52177,16 +52805,23 @@ var __webpack_exports__ = {};
|
|
|
52177
52805
|
setConfig("anvilUrl", configuredAnvilUrl);
|
|
52178
52806
|
logger_logger.success(`Set default Anvil server URL (anvilUrl) = ${configuredAnvilUrl}`);
|
|
52179
52807
|
const currentEditor = String(getConfig("preferredEditor") || "").trim().toLowerCase();
|
|
52808
|
+
const installedEditors = getInstalledPreferredEditors();
|
|
52809
|
+
if (0 === installedEditors.length) logger_logger.warn("No supported editor command was found in PATH. Leaving preferredEditor unset is recommended.");
|
|
52810
|
+
else if (installedEditors.length < preferredEditors.length) {
|
|
52811
|
+
const unavailableCount = preferredEditors.length - installedEditors.length;
|
|
52812
|
+
logger_logger.verbose(chalk_source.gray(`${unavailableCount} supported editor(s) are not installed and were hidden.`));
|
|
52813
|
+
}
|
|
52180
52814
|
const editorChoices = [
|
|
52181
52815
|
{
|
|
52182
52816
|
name: "None",
|
|
52183
52817
|
value: ""
|
|
52184
52818
|
},
|
|
52185
|
-
...
|
|
52819
|
+
...installedEditors.map((editor)=>({
|
|
52186
52820
|
name: editor,
|
|
52187
52821
|
value: editor
|
|
52188
52822
|
}))
|
|
52189
52823
|
];
|
|
52824
|
+
if (currentEditor && !editorChoices.some((choice)=>choice.value === currentEditor)) logger_logger.warn(`Configured preferredEditor '${currentEditor}' is not currently available in PATH.`);
|
|
52190
52825
|
const selectedEditor = await logger_logger.select("Preferred editor", editorChoices, editorChoices.some((choice)=>choice.value === currentEditor) ? currentEditor : "");
|
|
52191
52826
|
setConfig("preferredEditor", selectedEditor);
|
|
52192
52827
|
if (selectedEditor) logger_logger.success(`Set preferredEditor = ${selectedEditor}`);
|
|
@@ -52206,35 +52841,14 @@ var __webpack_exports__ = {};
|
|
|
52206
52841
|
} else logger_logger.warn("Skipping login.");
|
|
52207
52842
|
}
|
|
52208
52843
|
console.log();
|
|
52209
|
-
|
|
52210
|
-
|
|
52211
|
-
|
|
52212
|
-
{
|
|
52213
|
-
type: "input",
|
|
52214
|
-
name: "input",
|
|
52215
|
-
message: "App ID or app URL to checkout"
|
|
52216
|
-
}
|
|
52217
|
-
]);
|
|
52218
|
-
const checkoutInput = checkoutAnswer.input.trim();
|
|
52219
|
-
if (checkoutInput) {
|
|
52220
|
-
const preferredEditorCommand = getPreferredEditorCommand(selectedEditor);
|
|
52221
|
-
let openAfterCheckout = false;
|
|
52222
|
-
if (preferredEditorCommand) openAfterCheckout = await logger_logger.confirm(`Open checked out app in ${preferredEditorCommand} after checkout?`, true);
|
|
52223
|
-
else logger_logger.info("No preferred editor is configured, so open-in-editor is skipped.");
|
|
52224
|
-
await deps.executeCheckout({
|
|
52225
|
-
input: checkoutInput,
|
|
52226
|
-
url: configuredAnvilUrl,
|
|
52227
|
-
open: openAfterCheckout
|
|
52228
|
-
});
|
|
52229
|
-
} else logger_logger.info("No app provided; skipping checkout.");
|
|
52230
|
-
} else logger_logger.info("Skipping checkout.");
|
|
52231
|
-
console.log();
|
|
52232
|
-
logger_logger.success("Onboarding complete.");
|
|
52844
|
+
logger_logger.info(chalk_source.cyan("Next: anvil checkout"));
|
|
52845
|
+
logger_logger.info(chalk_source.gray("Run `anvil checkout` with no arguments to search and select your app."));
|
|
52846
|
+
logger_logger.success("Configuration complete.");
|
|
52233
52847
|
}
|
|
52234
|
-
function
|
|
52235
|
-
program.command("
|
|
52848
|
+
function registerConfigureCommand(program, version) {
|
|
52849
|
+
program.command("configure").description("Guided setup for configuration and login").action(async ()=>{
|
|
52236
52850
|
try {
|
|
52237
|
-
await
|
|
52851
|
+
await runConfigureFlow(version, configure_defaultDeps);
|
|
52238
52852
|
} catch (e) {
|
|
52239
52853
|
logger_logger.error("Error: " + errors_getErrorMessage(e));
|
|
52240
52854
|
process.exit(1);
|
|
@@ -52288,11 +52902,11 @@ var __webpack_exports__ = {};
|
|
|
52288
52902
|
console.log(chalk_source.cyan("To update, run one of the following commands:"));
|
|
52289
52903
|
console.log();
|
|
52290
52904
|
if ("win32" === process.platform) {
|
|
52291
|
-
console.log(chalk_source.gray(" PowerShell: ") + chalk_source.white("irm https://anvil.works/install
|
|
52292
|
-
console.log(chalk_source.gray(" CMD: ") + chalk_source.white("curl -fsSL https://anvil.works/install
|
|
52293
|
-
} else console.log(chalk_source.gray(" macOS/Linux: ") + chalk_source.white("curl -fsSL https://anvil.works/install
|
|
52294
|
-
console.log(chalk_source.gray(" npm: ") + chalk_source.white("npm
|
|
52295
|
-
console.log(chalk_source.gray(" pnpm: ") + chalk_source.white("pnpm
|
|
52905
|
+
console.log(chalk_source.gray(" PowerShell: ") + chalk_source.white("try { irm https://anvil.works/install-cli.ps1 | iex } catch { npm install -g @anvil-works/anvil-cli@latest }"));
|
|
52906
|
+
console.log(chalk_source.gray(" CMD: ") + chalk_source.white("curl -fsSL https://anvil.works/install-cli.cmd -o install.cmd && install.cmd && del install.cmd || npm install -g @anvil-works/anvil-cli@latest"));
|
|
52907
|
+
} else console.log(chalk_source.gray(" macOS/Linux: ") + chalk_source.white("curl -fsSL https://anvil.works/install-cli.sh | sh || npm install -g @anvil-works/anvil-cli@latest"));
|
|
52908
|
+
console.log(chalk_source.gray(" npm: ") + chalk_source.white("npm install -g @anvil-works/anvil-cli@latest"));
|
|
52909
|
+
console.log(chalk_source.gray(" pnpm: ") + chalk_source.white("pnpm add -g @anvil-works/anvil-cli@latest"));
|
|
52296
52910
|
console.log();
|
|
52297
52911
|
} catch (e) {
|
|
52298
52912
|
logger_logger.error("Error: " + e.message);
|
|
@@ -52317,7 +52931,7 @@ var __webpack_exports__ = {};
|
|
|
52317
52931
|
registerLogoutCommand(cli_program);
|
|
52318
52932
|
registerConfigCommand(cli_program);
|
|
52319
52933
|
registerVersionCommand(cli_program, VERSION);
|
|
52320
|
-
|
|
52934
|
+
registerConfigureCommand(cli_program, VERSION);
|
|
52321
52935
|
cli_program.command("update").description("Update anvil to the latest version").alias("u").action(async ()=>{
|
|
52322
52936
|
await handleUpdateCommand();
|
|
52323
52937
|
});
|