@anvil-works/anvil-cli 0.6.4 → 0.7.0-canary.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,4 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
3
- return 'undefined' == typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
4
- }();
5
2
  var __webpack_modules__ = {
6
3
  "./node_modules/.pnpm/@kwsites+file-exists@1.1.1/node_modules/@kwsites/file-exists/dist/index.js" (__unused_rspack_module, exports1, __webpack_require__) {
7
4
  "use strict";
@@ -31351,20 +31348,20 @@ var __webpack_exports__ = {};
31351
31348
  validateCheckoutDestination: ()=>validateCheckoutDestination,
31352
31349
  DeviceAuthorizationResponse: ()=>oauth_login_namespaceObject.DeviceAuthorizationResponse,
31353
31350
  OAuthTokenResponse: ()=>oauth_login_namespaceObject.OAuthTokenResponse,
31351
+ WatchSession: ()=>WatchSession_WatchSession,
31354
31352
  parseConfigSetValue: ()=>parseConfigSetValue,
31355
31353
  requestDeviceAuthorization: ()=>requestDeviceAuthorization,
31356
- validateAnvilApp: ()=>validation_validateAnvilApp,
31357
31354
  getGitPushUrl: ()=>anvil_api_getGitPushUrl,
31358
31355
  setAuthTokensForAccount: ()=>setAccountTokens,
31356
+ validateAnvilApp: ()=>validation_validateAnvilApp,
31359
31357
  ValidateAppIdResponse: ()=>anvil_api_namespaceObject.ValidateAppIdResponse,
31360
31358
  formatValidationPath: ()=>formatValidationPath,
31361
31359
  resolveAnvilUrl: ()=>resolveAnvilUrl,
31362
31360
  parseCheckoutInput: ()=>parseCheckoutInput,
31363
- login: ()=>login,
31361
+ login: ()=>auth_login,
31364
31362
  resetConfig: ()=>resetConfig,
31365
- resolveCheckoutUsername: ()=>resolveCheckoutUsername,
31366
- detectAppIdsByCommitLookup: ()=>anvil_api_detectAppIdsByCommitLookup,
31367
31363
  FormTemplateValidationResult: ()=>validators_namespaceObject.FormTemplateValidationResult,
31364
+ detectAppIdsByCommitLookup: ()=>anvil_api_detectAppIdsByCommitLookup,
31368
31365
  ValidationTarget: ()=>validators_namespaceObject.ValidationTarget,
31369
31366
  sanitizeDirectoryName: ()=>sanitizeDirectoryName,
31370
31367
  validatePath: ()=>validatePath,
@@ -31374,15 +31371,13 @@ var __webpack_exports__ = {};
31374
31371
  CheckoutAppListItem: ()=>anvil_api_namespaceObject.CheckoutAppListItem,
31375
31372
  getConfig: ()=>config_getConfig,
31376
31373
  CheckoutExecutionDeps: ()=>checkout_namespaceObject.CheckoutExecutionDeps,
31377
- openPathInEditorOrDefault: ()=>checkout_openPathInEditorOrDefault,
31374
+ ValidateBranchSyncStatusOptions: ()=>validation_namespaceObject.ValidateBranchSyncStatusOptions,
31378
31375
  BranchSyncStatus: ()=>validation_namespaceObject.BranchSyncStatus,
31379
31376
  getLatestVersion: ()=>getLatestVersion,
31380
31377
  isDirectoryNonEmpty: ()=>isDirectoryNonEmpty,
31381
31378
  syncToLatest: ()=>src_api_syncToLatest,
31382
31379
  filterCandidates: ()=>anvil_api_filterCandidates,
31383
- runInteractiveLoginFlow: ()=>runInteractiveLoginFlow,
31384
31380
  CheckoutOptions: ()=>checkout_namespaceObject.CheckoutOptions,
31385
- ensureCheckoutAuthToken: ()=>ensureCheckoutAuthToken,
31386
31381
  isPathInsideGitRepo: ()=>isPathInsideGitRepo,
31387
31382
  normalizeAnvilUrl: ()=>config_normalizeAnvilUrl,
31388
31383
  ValidationIssue: ()=>validators_namespaceObject.ValidationIssue,
@@ -31405,20 +31400,21 @@ var __webpack_exports__ = {};
31405
31400
  detectAppIdsFromAllRemotes: ()=>anvil_api_detectAppIdsFromAllRemotes,
31406
31401
  getWebSocketUrl: ()=>getWebSocketUrl,
31407
31402
  getAllConfig: ()=>getAllConfig,
31408
- isCommandAvailable: ()=>isCommandAvailable,
31403
+ isCommandAvailable: ()=>config_isCommandAvailable,
31409
31404
  validateAppId: ()=>anvil_api_validateAppId,
31410
31405
  pollDeviceAuthorization: ()=>pollDeviceAuthorization,
31411
31406
  getValidAuthToken: ()=>auth_getValidAuthToken,
31412
31407
  watch: ()=>src_api_watch,
31413
31408
  deleteConfig: ()=>deleteConfig,
31414
31409
  getGitFetchUrl: ()=>anvil_api_getGitFetchUrl,
31415
- resolveCheckoutUrl: ()=>resolveCheckoutUrl,
31416
31410
  PreferredEditor: ()=>config_namespaceObject.PreferredEditor,
31417
31411
  getAvailableAnvilUrls: ()=>getAvailableAnvilUrls,
31418
31412
  validateAnvilYaml: ()=>validateAnvilYaml,
31419
31413
  CheckoutCloneOptions: ()=>checkout_namespaceObject.CheckoutCloneOptions,
31414
+ ANVIL_SYNC_CLIENT_ID: ()=>ANVIL_SYNC_CLIENT_ID,
31420
31415
  formatCandidateLabel: ()=>anvil_api_formatCandidateLabel,
31421
31416
  StoredTokens: ()=>auth_namespaceObject.StoredTokens,
31417
+ CheckoutResult: ()=>checkout_namespaceObject.CheckoutResult,
31422
31418
  ParsedCheckoutInput: ()=>checkout_namespaceObject.ParsedCheckoutInput,
31423
31419
  getDefaultDestinationDirectory: ()=>getDefaultDestinationDirectory,
31424
31420
  lookupByCommit: ()=>lookupByCommit,
@@ -31434,9 +31430,9 @@ var __webpack_exports__ = {};
31434
31430
  WL: ()=>getInstalledPreferredEditors,
31435
31431
  uB: ()=>config_getPreferredEditorCommand,
31436
31432
  Bc: ()=>getSettableConfigKeys,
31437
- P$: ()=>isCommandAvailable,
31433
+ P$: ()=>config_isCommandAvailable,
31438
31434
  n: ()=>config_isDevMode,
31439
- Wj: ()=>isTestMode,
31435
+ Wj: ()=>config_isTestMode,
31440
31436
  Vl: ()=>config_normalizeAnvilUrl,
31441
31437
  PW: ()=>parseConfigSetValue,
31442
31438
  cx: ()=>preferredEditors,
@@ -31448,12 +31444,13 @@ var __webpack_exports__ = {};
31448
31444
  var auth_namespaceObject = {};
31449
31445
  __webpack_require__.r(auth_namespaceObject);
31450
31446
  __webpack_require__.d(auth_namespaceObject, {
31447
+ fg: ()=>ANVIL_SYNC_CLIENT_ID,
31451
31448
  Fr: ()=>auth_getAccountsForUrl,
31452
31449
  u5: ()=>getAvailableAnvilUrls,
31453
31450
  BG: ()=>getTokensForUrl,
31454
31451
  _p: ()=>auth_getValidAuthToken,
31455
31452
  Fi: ()=>auth_hasTokensForUrl,
31456
- iD: ()=>login,
31453
+ iD: ()=>auth_login,
31457
31454
  ri: ()=>logout,
31458
31455
  _d: ()=>auth_verifyAuth
31459
31456
  });
@@ -31492,21 +31489,16 @@ var __webpack_exports__ = {};
31492
31489
  __webpack_require__.r(oauth_login_namespaceObject);
31493
31490
  __webpack_require__.d(oauth_login_namespaceObject, {
31494
31491
  T_: ()=>pollDeviceAuthorization,
31495
- Z6: ()=>requestDeviceAuthorization,
31496
- Pe: ()=>runInteractiveLoginFlow
31492
+ Z6: ()=>requestDeviceAuthorization
31497
31493
  });
31498
31494
  var checkout_namespaceObject = {};
31499
31495
  __webpack_require__.r(checkout_namespaceObject);
31500
31496
  __webpack_require__.d(checkout_namespaceObject, {
31501
- oy: ()=>ensureCheckoutAuthToken,
31502
31497
  sF: ()=>executeCheckout,
31503
31498
  RD: ()=>getDefaultDestinationDirectory,
31504
31499
  A9: ()=>isDirectoryNonEmpty,
31505
31500
  oU: ()=>isPathInsideGitRepo,
31506
- GJ: ()=>checkout_openPathInEditorOrDefault,
31507
31501
  Qx: ()=>parseCheckoutInput,
31508
- GK: ()=>resolveCheckoutUrl,
31509
- XM: ()=>resolveCheckoutUsername,
31510
31502
  KV: ()=>sanitizeDirectoryName,
31511
31503
  Bc: ()=>validateCheckoutDestination
31512
31504
  });
@@ -32792,13 +32784,13 @@ var __webpack_exports__ = {};
32792
32784
  values
32793
32785
  };
32794
32786
  }
32795
- function esm_configFilePath(filePath) {
32787
+ function configFilePath(filePath) {
32796
32788
  return filePath.replace(/^(file):/, "");
32797
32789
  }
32798
32790
  function* configParser(text, requestedKey = null) {
32799
32791
  const lines = text.split("\0");
32800
32792
  for(let i = 0, max = lines.length - 1; i < max;){
32801
- const file = esm_configFilePath(lines[i++]);
32793
+ const file = configFilePath(lines[i++]);
32802
32794
  let value = lines[i++];
32803
32795
  let key = requestedKey;
32804
32796
  if (value.includes("\n")) {
@@ -39802,7 +39794,7 @@ var __webpack_exports__ = {};
39802
39794
  return `anvil-cli:${url}`;
39803
39795
  }
39804
39796
  function keychainGet(url, username) {
39805
- if (isTestMode()) return null;
39797
+ if (config_isTestMode()) return null;
39806
39798
  const Ctor = loadKeyring();
39807
39799
  if (!Ctor) return null;
39808
39800
  try {
@@ -39818,7 +39810,7 @@ var __webpack_exports__ = {};
39818
39810
  }
39819
39811
  }
39820
39812
  function keychainSet(url, username, secrets) {
39821
- if (isTestMode()) return false;
39813
+ if (config_isTestMode()) return false;
39822
39814
  const Ctor = loadKeyring();
39823
39815
  if (!Ctor) return false;
39824
39816
  try {
@@ -39830,7 +39822,7 @@ var __webpack_exports__ = {};
39830
39822
  }
39831
39823
  }
39832
39824
  function keychainDelete(url, username) {
39833
- if (isTestMode()) return;
39825
+ if (config_isTestMode()) return;
39834
39826
  const Ctor = loadKeyring();
39835
39827
  if (!Ctor) return;
39836
39828
  try {
@@ -39841,12 +39833,13 @@ var __webpack_exports__ = {};
39841
39833
  const EMPTY_TOKENS = {
39842
39834
  authToken: null,
39843
39835
  refreshToken: null,
39844
- authTokenExpiresAt: null
39836
+ authTokenExpiresAt: null,
39837
+ clientId: null
39845
39838
  };
39846
39839
  function isAccountTokens(value) {
39847
39840
  if (!value || "object" != typeof value || Array.isArray(value)) return false;
39848
39841
  const obj = value;
39849
- return ("authToken" in obj || "refreshToken" in obj || "authTokenExpiresAt" in obj) && (null === obj.authToken || "string" == typeof obj.authToken) && (null === obj.refreshToken || "string" == typeof obj.refreshToken) && (null === obj.authTokenExpiresAt || "number" == typeof obj.authTokenExpiresAt);
39842
+ return ("authToken" in obj || "refreshToken" in obj || "authTokenExpiresAt" in obj) && (null === obj.authToken || "string" == typeof obj.authToken) && (null === obj.refreshToken || "string" == typeof obj.refreshToken) && (null === obj.authTokenExpiresAt || "number" == typeof obj.authTokenExpiresAt) && (!("clientId" in obj) || null === obj.clientId || "string" == typeof obj.clientId);
39850
39843
  }
39851
39844
  function isUrlTokens(value) {
39852
39845
  if (!value || "object" != typeof value || Array.isArray(value)) return false;
@@ -39910,7 +39903,8 @@ var __webpack_exports__ = {};
39910
39903
  if (keychainOk) store[normalized][username] = {
39911
39904
  authToken: null,
39912
39905
  refreshToken: null,
39913
- authTokenExpiresAt: tokens.authTokenExpiresAt
39906
+ authTokenExpiresAt: tokens.authTokenExpiresAt,
39907
+ clientId: tokens.clientId ?? null
39914
39908
  };
39915
39909
  else store[normalized][username] = tokens;
39916
39910
  setTokenStore(store);
@@ -40009,7 +40003,7 @@ var __webpack_exports__ = {};
40009
40003
  "verbose",
40010
40004
  "preferredEditor"
40011
40005
  ];
40012
- function isTestMode() {
40006
+ function config_isTestMode() {
40013
40007
  return "test" === process.env.NODE_ENV || !!process.env.RSTEST;
40014
40008
  }
40015
40009
  function setupConfConfig() {
@@ -40042,7 +40036,7 @@ var __webpack_exports__ = {};
40042
40036
  return wrapper;
40043
40037
  }
40044
40038
  let config_config;
40045
- config_config = isTestMode() ? setupMockConfConfig() : setupConfConfig();
40039
+ config_config = config_isTestMode() ? setupMockConfConfig() : setupConfConfig();
40046
40040
  function setConfig(key, value) {
40047
40041
  config_config.set(key, value);
40048
40042
  }
@@ -40129,7 +40123,7 @@ var __webpack_exports__ = {};
40129
40123
  return false;
40130
40124
  }
40131
40125
  }
40132
- function isCommandAvailable(command, env = process.env) {
40126
+ function config_isCommandAvailable(command, env = process.env) {
40133
40127
  const executable = extractExecutableFromCommand(command);
40134
40128
  if (!executable) return false;
40135
40129
  const hasPathSeparator = executable.includes(external_path_default().sep) || executable.includes("/");
@@ -40156,7 +40150,7 @@ var __webpack_exports__ = {};
40156
40150
  return false;
40157
40151
  }
40158
40152
  function getInstalledPreferredEditors() {
40159
- return preferredEditors.filter((editor)=>isCommandAvailable(config_getPreferredEditorCommand(editor)));
40153
+ return preferredEditors.filter((editor)=>config_isCommandAvailable(config_getPreferredEditorCommand(editor)));
40160
40154
  }
40161
40155
  function getAllConfig() {
40162
40156
  return config_config.store;
@@ -40174,7 +40168,7 @@ var __webpack_exports__ = {};
40174
40168
  function resolveAnvilUrl() {
40175
40169
  const fromConfig = config_getConfig("anvilUrl");
40176
40170
  if ("string" == typeof fromConfig && fromConfig.trim()) return fromConfig.trim();
40177
- if (isTestMode()) return process.env.ANVIL_API_ORIGIN || "http://localhost:3000";
40171
+ if (config_isTestMode()) return process.env.ANVIL_API_ORIGIN || "http://localhost:3000";
40178
40172
  return config_isDevMode() ? "http://localhost:3000" : "https://anvil.works";
40179
40173
  }
40180
40174
  function config_isDevMode() {
@@ -40188,6 +40182,10 @@ var __webpack_exports__ = {};
40188
40182
  function globalConfig_getGlobalOutputConfig() {
40189
40183
  return globalOutputConfig;
40190
40184
  }
40185
+ function globalConfig_assertCanPrompt(action = "This command", explicitAlternative = "Pass explicit flags instead.") {
40186
+ if (globalOutputConfig.jsonMode) throw new Error(`${action} requires interactive input, but --json disables prompts. ${explicitAlternative}`);
40187
+ if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error(`${action} requires interactive input, but stdin/stdout is not a TTY. ${explicitAlternative}`);
40188
+ }
40191
40189
  const logger_timestamp = ()=>new Date().toISOString();
40192
40190
  const logger_verboseTimestamp = ()=>{
40193
40191
  const now = new Date();
@@ -40225,11 +40223,11 @@ var __webpack_exports__ = {};
40225
40223
  });
40226
40224
  }
40227
40225
  debug(...args) {
40228
- if (config_isDevMode() && !isTestMode()) if (this.jsonMode) this.logJson("debug", args.map(String).join(" "));
40226
+ if (config_isDevMode() && !config_isTestMode()) if (this.jsonMode) this.logJson("debug", args.map(String).join(" "));
40229
40227
  else this.log(chalk_source.gray("[DEV]"), ...args);
40230
40228
  }
40231
40229
  verbose(...args) {
40232
- if (config_getConfig("verbose") && !isTestMode()) if (this.jsonMode) this.logJson("verbose", args.map(String).join(" "));
40230
+ if (config_getConfig("verbose") && !config_isTestMode()) if (this.jsonMode) this.logJson("verbose", args.map(String).join(" "));
40233
40231
  else this.log(chalk_source.gray(`[${logger_verboseTimestamp()}]`), ...args);
40234
40232
  }
40235
40233
  info(...args) {
@@ -40284,14 +40282,32 @@ var __webpack_exports__ = {};
40284
40282
  resume() {
40285
40283
  this.paused = false;
40286
40284
  }
40287
- async prompt(questions) {
40285
+ async prompt(questions, options) {
40286
+ globalConfig_assertCanPrompt(options?.action ?? "Prompt", options?.nonInteractiveHint);
40288
40287
  throw new Error("Prompting not supported in DefaultLogger. Use CLILogger for interactive prompts.");
40289
40288
  }
40290
- async confirm(message, defaultValue = true) {
40291
- throw new Error("Prompting not supported in DefaultLogger. Use CLILogger for interactive prompts.");
40289
+ async confirm(message, defaultValue = true, options) {
40290
+ const answer = await this.prompt([
40291
+ {
40292
+ type: "confirm",
40293
+ name: "value",
40294
+ message,
40295
+ default: defaultValue
40296
+ }
40297
+ ], options);
40298
+ return answer.value;
40292
40299
  }
40293
- async select(message, choices, defaultValue) {
40294
- throw new Error("Prompting not supported in DefaultLogger. Use CLILogger for interactive prompts.");
40300
+ async select(message, choices, defaultValue, options) {
40301
+ const answer = await this.prompt([
40302
+ {
40303
+ type: "list",
40304
+ name: "value",
40305
+ message,
40306
+ choices,
40307
+ default: defaultValue
40308
+ }
40309
+ ], options);
40310
+ return answer.value;
40295
40311
  }
40296
40312
  }
40297
40313
  let logger_logger = new DefaultLogger();
@@ -42480,6 +42496,7 @@ var __webpack_exports__ = {};
42480
42496
  function getDefaultAnvilUrl() {
42481
42497
  return resolveAnvilUrl();
42482
42498
  }
42499
+ const ANVIL_SYNC_CLIENT_ID = "anvil-sync";
42483
42500
  async function auth_verifyAuth(authToken, anvilUrl = getDefaultAnvilUrl()) {
42484
42501
  try {
42485
42502
  const resp = await fetch(`${anvilUrl}/ide/api/_/user`, {
@@ -42499,7 +42516,7 @@ var __webpack_exports__ = {};
42499
42516
  throw createAuthError.invalid(`Network error: ${e.message}`);
42500
42517
  }
42501
42518
  }
42502
- async function refreshAccessToken(refreshToken, anvilUrl = getDefaultAnvilUrl()) {
42519
+ async function refreshAccessToken(refreshToken, anvilUrl = getDefaultAnvilUrl(), clientId = ANVIL_SYNC_CLIENT_ID) {
42503
42520
  try {
42504
42521
  const tokenResponse = await fetch(`${anvilUrl}/oauth/token`, {
42505
42522
  method: "POST",
@@ -42509,7 +42526,7 @@ var __webpack_exports__ = {};
42509
42526
  body: new URLSearchParams({
42510
42527
  grant_type: "refresh_token",
42511
42528
  refresh_token: refreshToken,
42512
- client_id: "anvil-sync"
42529
+ client_id: clientId
42513
42530
  })
42514
42531
  });
42515
42532
  if (!tokenResponse.ok) {
@@ -42535,7 +42552,8 @@ var __webpack_exports__ = {};
42535
42552
  if (!tokens.authToken && !tokens.refreshToken) throw createAuthError.required("Not logged in. Please log in first.");
42536
42553
  const isExpired = null !== tokens.authTokenExpiresAt && tokens.authTokenExpiresAt <= Math.floor(Date.now() / 1000) + 60;
42537
42554
  if (tokens.refreshToken && isExpired) try {
42538
- const tokenData = await refreshAccessToken(tokens.refreshToken, normalized);
42555
+ const clientId = tokens.clientId ?? ANVIL_SYNC_CLIENT_ID;
42556
+ const tokenData = await refreshAccessToken(tokens.refreshToken, normalized, clientId);
42539
42557
  const newExpiresAt = Math.floor(Date.now() / 1000) + tokenData.expires_in;
42540
42558
  let accountUsername = username;
42541
42559
  if (!accountUsername) {
@@ -42552,7 +42570,8 @@ var __webpack_exports__ = {};
42552
42570
  setAccountTokens(normalized, accountUsername, {
42553
42571
  authToken: tokenData.access_token,
42554
42572
  refreshToken: tokenData.refresh_token,
42555
- authTokenExpiresAt: newExpiresAt
42573
+ authTokenExpiresAt: newExpiresAt,
42574
+ clientId
42556
42575
  });
42557
42576
  return tokenData.access_token;
42558
42577
  } catch (e) {
@@ -42570,14 +42589,15 @@ var __webpack_exports__ = {};
42570
42589
  if (account) deleteAccountTokens(normalized, account);
42571
42590
  }
42572
42591
  }
42573
- async function login(anvilUrl, tokenData) {
42592
+ async function auth_login(anvilUrl, tokenData) {
42574
42593
  const normalized = config_normalizeAnvilUrl(anvilUrl);
42575
42594
  const expiresAt = Math.floor(Date.now() / 1000) + tokenData.expires_in;
42576
42595
  const username = await auth_verifyAuth(tokenData.access_token, normalized);
42577
42596
  setAccountTokens(normalized, username, {
42578
42597
  authToken: tokenData.access_token,
42579
42598
  refreshToken: tokenData.refresh_token,
42580
- authTokenExpiresAt: expiresAt
42599
+ authTokenExpiresAt: expiresAt,
42600
+ clientId: ANVIL_SYNC_CLIENT_ID
42581
42601
  });
42582
42602
  return {
42583
42603
  success: true,
@@ -44020,7 +44040,9 @@ var __webpack_exports__ = {};
44020
44040
  };
44021
44041
  return null;
44022
44042
  }
44023
- async function loadFormTemplateData(repoPath, relativePath, stagedOnly, kind, format) {
44043
+ async function loadFormTemplateData(relativePath, templateInfo, context) {
44044
+ const { repoPath, stagedOnly = false } = context;
44045
+ const { kind, format } = templateInfo;
44024
44046
  try {
44025
44047
  const content = await readFileContent(repoPath, relativePath, stagedOnly);
44026
44048
  if ("yaml" === format) {
@@ -44108,7 +44130,8 @@ var __webpack_exports__ = {};
44108
44130
  if (formTemplateInfo) return "forms";
44109
44131
  return null;
44110
44132
  }
44111
- async function validateRename(fromPath, toPath, repoPath, editorYaml) {
44133
+ async function validateRename(fromPath, toPath, context) {
44134
+ const { repoPath, editorYaml } = context;
44112
44135
  const fromEntityType = await getEntityTypeFromPath(repoPath, fromPath, editorYaml);
44113
44136
  const toEntityType = await getEntityTypeFromPath(repoPath, toPath, editorYaml);
44114
44137
  if (null === fromEntityType || null === toEntityType) return {
@@ -44266,7 +44289,8 @@ var __webpack_exports__ = {};
44266
44289
  }
44267
44290
  return filtered;
44268
44291
  }
44269
- async function routeFileChange(repoPath, relativePath, changeType, editorYaml, stagedOnly = false, fromPath) {
44292
+ async function routeFileChange(change, context) {
44293
+ const { relativePath, changeType, fromPath } = change;
44270
44294
  logger_logger.verbose(chalk_source.gray(`Routing ${changeType}: ${relativePath}${fromPath ? ` (from: ${fromPath})` : ""}`));
44271
44295
  if (isGitRelatedFile(relativePath)) return {
44272
44296
  type: "ignore",
@@ -44279,9 +44303,12 @@ var __webpack_exports__ = {};
44279
44303
  type: "ignore",
44280
44304
  reason: "Rename operation missing from path"
44281
44305
  };
44282
- return await handleRename(repoPath, fromPath, relativePath, editorYaml, stagedOnly);
44306
+ return await handleRename({
44307
+ fromPath,
44308
+ toPath: relativePath
44309
+ }, context);
44283
44310
  }
44284
- return await routeSavableChange(repoPath, relativePath, changeType, editorYaml, stagedOnly);
44311
+ return await routeSavableChange(change, context);
44285
44312
  }
44286
44313
  function isGitRelatedFile(relativePath) {
44287
44314
  return ".git" === relativePath || relativePath.startsWith(".git/") || relativePath.endsWith("/.git");
@@ -44300,47 +44327,60 @@ var __webpack_exports__ = {};
44300
44327
  const parts = relativePath.split("/");
44301
44328
  return 2 === parts.length;
44302
44329
  },
44303
- handle: (repoPath, relativePath, changeType, editorYaml, stagedOnly)=>handleScriptsChange(repoPath, relativePath, editorYaml, changeType, stagedOnly)
44330
+ handle: handleScriptsChange
44304
44331
  },
44305
44332
  {
44306
44333
  matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py"),
44307
- handle: (repoPath, relativePath, changeType, editorYaml, stagedOnly)=>handleServerCodeChange(repoPath, relativePath, editorYaml, changeType, stagedOnly)
44334
+ handle: handleServerCodeChange
44308
44335
  },
44309
44336
  {
44310
44337
  matches: (relativePath)=>relativePath.startsWith("client_code/") && relativePath.endsWith(".py"),
44311
- handle: (repoPath, relativePath, changeType, editorYaml, stagedOnly)=>handleClientCodeChange(repoPath, relativePath, editorYaml, changeType, stagedOnly)
44338
+ handle: handleClientCodeChange
44312
44339
  },
44313
44340
  {
44314
44341
  matches: (relativePath)=>null !== detectFormTemplate(relativePath),
44315
- handle: (repoPath, relativePath, changeType, editorYaml, stagedOnly)=>handleFormTemplateChange(repoPath, relativePath, editorYaml, changeType, stagedOnly)
44342
+ handle: handleFormTemplateChange
44316
44343
  },
44317
44344
  {
44318
44345
  matches: (relativePath)=>"theme/parameters.yaml" === relativePath,
44319
- handle: (repoPath, relativePath, changeType, editorYaml, stagedOnly)=>handleThemeParametersChange(repoPath, relativePath, stagedOnly)
44346
+ handle: handleThemeParametersChange
44320
44347
  },
44321
44348
  {
44322
44349
  matches: (relativePath)=>relativePath.startsWith("theme/assets/"),
44323
- handle: (repoPath, relativePath, changeType, editorYaml, stagedOnly)=>handleAssetChange(repoPath, relativePath, changeType, editorYaml, stagedOnly)
44350
+ handle: handleAssetChange
44324
44351
  },
44325
44352
  {
44326
44353
  matches: ()=>true,
44327
- handle: (repoPath, relativePath, changeType, editorYaml, stagedOnly)=>handleExtraFileChange(repoPath, relativePath, stagedOnly)
44354
+ handle: handleExtraFileChange
44328
44355
  }
44329
44356
  ];
44330
- async function handleRename(repoPath, fromPath, toPath, editorYaml, stagedOnly) {
44331
- const validation = await validateRename(fromPath, toPath, repoPath, editorYaml);
44357
+ async function handleRename(rename, context) {
44358
+ const { fromPath, toPath } = rename;
44359
+ const validation = await validateRename(fromPath, toPath, context);
44332
44360
  if (!validation.valid) {
44333
44361
  logger_logger.verbose(chalk_source.yellow(`Rename invalid (${validation.reason}), falling back to unlink + add`));
44334
- const unlinkResult = await routeFileChange(repoPath, fromPath, "unlink", editorYaml, stagedOnly);
44335
- const addResult = await routeFileChange(repoPath, toPath, "add", editorYaml, stagedOnly);
44362
+ const unlinkResult = await routeFileChange({
44363
+ relativePath: fromPath,
44364
+ changeType: "unlink"
44365
+ }, context);
44366
+ const addResult = await routeFileChange({
44367
+ relativePath: toPath,
44368
+ changeType: "add"
44369
+ }, context);
44336
44370
  return [
44337
44371
  unlinkResult,
44338
44372
  addResult
44339
44373
  ].flat();
44340
44374
  }
44341
- return await handleRenameOperation(repoPath, fromPath, toPath, validation.entityType, editorYaml, stagedOnly);
44375
+ return await handleRenameOperation({
44376
+ fromPath,
44377
+ toPath,
44378
+ entityType: validation.entityType
44379
+ }, context);
44342
44380
  }
44343
- async function handleRenameOperation(repoPath, fromPath, toPath, entityType, editorYaml, stagedOnly) {
44381
+ async function handleRenameOperation(rename, context) {
44382
+ const { repoPath, editorYaml, stagedOnly = false } = context;
44383
+ const { fromPath, toPath, entityType } = rename;
44344
44384
  let oldName;
44345
44385
  let newName;
44346
44386
  let prefix = [];
@@ -44349,10 +44389,10 @@ var __webpack_exports__ = {};
44349
44389
  let isPackage = false;
44350
44390
  let actualToPath = toPath;
44351
44391
  if ("scripts" === entityType) {
44352
- const toRenameResult = await handlePathRenaming(repoPath, toPath, "scripts", stagedOnly);
44392
+ const toRenameResult = await handlePathRenaming(toPath, "scripts", context);
44353
44393
  if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
44354
44394
  actualToPath = toRenameResult.newRelativePath;
44355
- const fromRenameResult = await handlePathRenaming(repoPath, fromPath, "scripts", stagedOnly);
44395
+ const fromRenameResult = await handlePathRenaming(fromPath, "scripts", context);
44356
44396
  oldName = fromRenameResult.pythonifiedName;
44357
44397
  newName = toRenameResult.pythonifiedName;
44358
44398
  prefix = [
@@ -44364,10 +44404,10 @@ var __webpack_exports__ = {};
44364
44404
  code
44365
44405
  });
44366
44406
  } else if ("server_modules" === entityType) {
44367
- const toRenameResult = await handlePathRenaming(repoPath, toPath, "server_code", stagedOnly);
44407
+ const toRenameResult = await handlePathRenaming(toPath, "server_code", context);
44368
44408
  if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
44369
44409
  actualToPath = toRenameResult.newRelativePath;
44370
- const fromRenameResult = await handlePathRenaming(repoPath, fromPath, "server_code", stagedOnly);
44410
+ const fromRenameResult = await handlePathRenaming(fromPath, "server_code", context);
44371
44411
  oldName = fromRenameResult.pythonifiedName;
44372
44412
  newName = toRenameResult.pythonifiedName;
44373
44413
  prefix = [
@@ -44381,10 +44421,10 @@ var __webpack_exports__ = {};
44381
44421
  is_package: isPackage
44382
44422
  });
44383
44423
  } else if ("modules" === entityType) {
44384
- const toRenameResult = await handlePathRenaming(repoPath, toPath, "client_code", stagedOnly);
44424
+ const toRenameResult = await handlePathRenaming(toPath, "client_code", context);
44385
44425
  if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
44386
44426
  actualToPath = toRenameResult.newRelativePath;
44387
- const fromRenameResult = await handlePathRenaming(repoPath, fromPath, "client_code", stagedOnly);
44427
+ const fromRenameResult = await handlePathRenaming(fromPath, "client_code", context);
44388
44428
  oldName = fromRenameResult.pythonifiedName;
44389
44429
  newName = toRenameResult.pythonifiedName;
44390
44430
  isPackage = actualToPath.endsWith("__init__.py");
@@ -44402,10 +44442,10 @@ var __webpack_exports__ = {};
44402
44442
  type: "ignore",
44403
44443
  reason: "Form template rename to .yaml file is only supported when entire form is renamed"
44404
44444
  };
44405
- const toRenameResult = await handlePathRenaming(repoPath, toPath, "client_code", stagedOnly);
44445
+ const toRenameResult = await handlePathRenaming(toPath, "client_code", context);
44406
44446
  if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
44407
44447
  actualToPath = toRenameResult.newRelativePath;
44408
- const fromRenameResult = await handlePathRenaming(repoPath, fromPath, "client_code", stagedOnly);
44448
+ const fromRenameResult = await handlePathRenaming(fromPath, "client_code", context);
44409
44449
  oldName = fromRenameResult.pythonifiedName;
44410
44450
  const isPackageInit = actualToPath.endsWith("__init__.py");
44411
44451
  const kind = isPackageInit ? "package" : "module";
@@ -44414,7 +44454,10 @@ var __webpack_exports__ = {};
44414
44454
  type: "ignore",
44415
44455
  reason: "Form template not found for rename destination"
44416
44456
  };
44417
- const result = await buildFormTemplateData(repoPath, templateInfo.relativePath, stagedOnly, kind, templateInfo.format);
44457
+ const result = await buildFormTemplateData(templateInfo.relativePath, {
44458
+ kind,
44459
+ format: templateInfo.format
44460
+ }, context);
44418
44461
  if (result.ignoreResult) return result.ignoreResult;
44419
44462
  newName = result.className;
44420
44463
  prefix = [
@@ -44462,7 +44505,9 @@ var __webpack_exports__ = {};
44462
44505
  content: payload
44463
44506
  };
44464
44507
  }
44465
- async function routeSavableChange(repoPath, relativePath, changeType, editorYaml, stagedOnly = false) {
44508
+ async function routeSavableChange(change, context) {
44509
+ const { repoPath, editorYaml, stagedOnly = false } = context;
44510
+ const { relativePath, changeType } = change;
44466
44511
  if ("anvil.yaml" === relativePath) return {
44467
44512
  type: "ignore",
44468
44513
  reason: "anvil.yaml handled specially (multiple save paths)"
@@ -44506,13 +44551,15 @@ var __webpack_exports__ = {};
44506
44551
  };
44507
44552
  }
44508
44553
  if ("unlink" === changeType) return await handleFileDeletion(repoPath, relativePath, editorYaml);
44509
- for (const route of ROUTES)if (route.matches(relativePath)) return await route.handle(repoPath, relativePath, changeType, editorYaml, stagedOnly);
44554
+ for (const route of ROUTES)if (route.matches(relativePath)) return await route.handle(change, context);
44510
44555
  return {
44511
44556
  type: "ignore",
44512
44557
  reason: "Not a recognized Anvil file type"
44513
44558
  };
44514
44559
  }
44515
- async function handleThemeParametersChange(repoPath, relativePath, stagedOnly = false) {
44560
+ async function handleThemeParametersChange(change, context) {
44561
+ const { repoPath, stagedOnly = false } = context;
44562
+ const { relativePath } = change;
44516
44563
  const content = await readFileContent(repoPath, relativePath, stagedOnly);
44517
44564
  const parametersData = jsYaml.load(content);
44518
44565
  return {
@@ -44524,7 +44571,9 @@ var __webpack_exports__ = {};
44524
44571
  content: parametersData
44525
44572
  };
44526
44573
  }
44527
- async function handleExtraFileChange(repoPath, relativePath, stagedOnly = false) {
44574
+ async function handleExtraFileChange(change, context) {
44575
+ const { repoPath, stagedOnly = false } = context;
44576
+ const { relativePath } = change;
44528
44577
  const content = await readBinaryFileContent(repoPath, relativePath, stagedOnly);
44529
44578
  const base64Content = content.toString("base64");
44530
44579
  const pathParts = [
@@ -44537,7 +44586,9 @@ var __webpack_exports__ = {};
44537
44586
  content: base64Content
44538
44587
  };
44539
44588
  }
44540
- async function handleDirectoryRenaming(repoPath, originalParts, pythonifiedParts, baseDir) {
44589
+ async function handleDirectoryRenaming(rename, context) {
44590
+ const { repoPath } = context;
44591
+ const { originalParts, pythonifiedParts, baseDir } = rename;
44541
44592
  const needsRename = originalParts.some((part, idx)=>part !== pythonifiedParts[idx]);
44542
44593
  if (!needsRename) return null;
44543
44594
  const needsDirRename = originalParts.slice(0, -1).some((part, idx)=>part !== pythonifiedParts[idx]);
@@ -44555,7 +44606,9 @@ var __webpack_exports__ = {};
44555
44606
  }
44556
44607
  return null;
44557
44608
  }
44558
- async function renameIfNeeded(repoPath, relativePath, originalNameOrParts, baseDir) {
44609
+ async function renameIfNeeded(rename, context) {
44610
+ const { repoPath } = context;
44611
+ const { relativePath, originalNameOrParts, baseDir } = rename;
44559
44612
  let pythonifiedName;
44560
44613
  let pythonifiedParts;
44561
44614
  let needsRename;
@@ -44593,8 +44646,10 @@ var __webpack_exports__ = {};
44593
44646
  ignoreResult
44594
44647
  };
44595
44648
  }
44596
- async function handleScriptsChange(repoPath, relativePath, editorYaml, changeType, stagedOnly = false) {
44597
- const renameResult = await handlePathRenaming(repoPath, relativePath, "scripts", stagedOnly);
44649
+ async function handleScriptsChange(change, context) {
44650
+ const { repoPath, editorYaml, stagedOnly = false } = context;
44651
+ const { relativePath, changeType } = change;
44652
+ const renameResult = await handlePathRenaming(relativePath, "scripts", context);
44598
44653
  if (renameResult.ignoreResult) return renameResult.ignoreResult;
44599
44654
  const actualPath = renameResult.newRelativePath;
44600
44655
  const content = await readFileContent(repoPath, actualPath, stagedOnly);
@@ -44616,8 +44671,10 @@ var __webpack_exports__ = {};
44616
44671
  ]
44617
44672
  });
44618
44673
  }
44619
- async function handleServerCodeChange(repoPath, relativePath, editorYaml, changeType, stagedOnly = false) {
44620
- const renameResult = await handlePathRenaming(repoPath, relativePath, "server_code", stagedOnly);
44674
+ async function handleServerCodeChange(change, context) {
44675
+ const { repoPath, editorYaml, stagedOnly = false } = context;
44676
+ const { relativePath, changeType } = change;
44677
+ const renameResult = await handlePathRenaming(relativePath, "server_code", context);
44621
44678
  if (renameResult.ignoreResult) return renameResult.ignoreResult;
44622
44679
  const actualPath = renameResult.newRelativePath;
44623
44680
  const isPackage = actualPath.endsWith("__init__.py");
@@ -44642,8 +44699,10 @@ var __webpack_exports__ = {};
44642
44699
  ]
44643
44700
  });
44644
44701
  }
44645
- async function handleClientCodeFormChange(repoPath, relativePath, className, templatePath, format, kind, changeType, editorYaml, stagedOnly) {
44646
- const result = await buildFormTemplateData(repoPath, templatePath, stagedOnly, kind, format);
44702
+ async function handleClientCodeFormChange(options, context) {
44703
+ const { editorYaml } = context;
44704
+ const { templatePath, templateInfo, changeType } = options;
44705
+ const result = await buildFormTemplateData(templatePath, templateInfo, context);
44647
44706
  if (result.ignoreResult) return result.ignoreResult;
44648
44707
  const { formData, className: extractedClassName } = result;
44649
44708
  return handleIdBasedOperation({
@@ -44661,30 +44720,47 @@ var __webpack_exports__ = {};
44661
44720
  ]
44662
44721
  });
44663
44722
  }
44664
- async function handlePathRenaming(repoPath, relativePath, baseDir, stagedOnly) {
44723
+ async function handlePathRenaming(relativePath, baseDir, context) {
44665
44724
  const parts = relativePath.slice(0, -3).split("/");
44666
44725
  const originalParts = parts.slice(1);
44667
44726
  const pythonifiedParts = originalParts.map(pythonifyName);
44668
44727
  const pythonifiedName = extractPythonName(relativePath);
44669
- const dirRenameResult = await handleDirectoryRenaming(repoPath, originalParts, pythonifiedParts, baseDir);
44728
+ const dirRenameResult = await handleDirectoryRenaming({
44729
+ originalParts,
44730
+ pythonifiedParts,
44731
+ baseDir
44732
+ }, context);
44670
44733
  if (dirRenameResult) return {
44671
44734
  pythonifiedName,
44672
44735
  pythonifiedParts,
44673
44736
  newRelativePath: relativePath,
44674
44737
  ignoreResult: dirRenameResult
44675
44738
  };
44676
- const renameResult = await renameIfNeeded(repoPath, relativePath, originalParts, baseDir);
44739
+ const renameResult = await renameIfNeeded({
44740
+ relativePath,
44741
+ originalNameOrParts: originalParts,
44742
+ baseDir
44743
+ }, context);
44677
44744
  return renameResult;
44678
44745
  }
44679
- async function handleClientCodeChange(repoPath, relativePath, editorYaml, changeType, stagedOnly = false) {
44680
- const renameResult = await handlePathRenaming(repoPath, relativePath, "client_code", stagedOnly);
44746
+ async function handleClientCodeChange(change, context) {
44747
+ const { repoPath, editorYaml, stagedOnly = false } = context;
44748
+ const { relativePath, changeType } = change;
44749
+ const renameResult = await handlePathRenaming(relativePath, "client_code", context);
44681
44750
  if (renameResult.ignoreResult) return renameResult.ignoreResult;
44682
44751
  const actualPath = renameResult.newRelativePath;
44683
44752
  const isPackageInit = actualPath.endsWith("__init__.py");
44684
44753
  const kind = isPackageInit ? "package" : "module";
44685
44754
  const className = renameResult.pythonifiedName;
44686
44755
  const templateInfo = findFormTemplateForCodePath(repoPath, actualPath, kind);
44687
- if (templateInfo) return await handleClientCodeFormChange(repoPath, actualPath, className, templateInfo.relativePath, templateInfo.format, kind, changeType, editorYaml, stagedOnly);
44756
+ if (templateInfo) return await handleClientCodeFormChange({
44757
+ templatePath: templateInfo.relativePath,
44758
+ templateInfo: {
44759
+ format: templateInfo.format,
44760
+ kind
44761
+ },
44762
+ changeType
44763
+ }, context);
44688
44764
  const content = await readFileContent(repoPath, actualPath, stagedOnly);
44689
44765
  return handleIdBasedOperation({
44690
44766
  entityType: "modules",
@@ -44719,8 +44795,10 @@ var __webpack_exports__ = {};
44719
44795
  }
44720
44796
  return formData;
44721
44797
  }
44722
- async function buildFormTemplateData(repoPath, relativePath, stagedOnly, kind, format) {
44723
- const loadResult = await loadFormTemplateData(repoPath, relativePath, stagedOnly, kind, format);
44798
+ async function buildFormTemplateData(relativePath, templateInfo, context) {
44799
+ const { repoPath, stagedOnly = false } = context;
44800
+ const { kind } = templateInfo;
44801
+ const loadResult = await loadFormTemplateData(relativePath, templateInfo, context);
44724
44802
  if (false === loadResult.ok) return {
44725
44803
  formData: {},
44726
44804
  className: "",
@@ -44754,7 +44832,9 @@ var __webpack_exports__ = {};
44754
44832
  ignoreResult: null
44755
44833
  };
44756
44834
  }
44757
- async function handleFormTemplateChange(repoPath, relativePath, editorYaml, changeType, stagedOnly) {
44835
+ async function handleFormTemplateChange(change, context) {
44836
+ const { editorYaml } = context;
44837
+ const { relativePath, changeType } = change;
44758
44838
  const templateInfo = detectFormTemplate(relativePath);
44759
44839
  if (!templateInfo) return {
44760
44840
  type: "ignore",
@@ -44762,7 +44842,10 @@ var __webpack_exports__ = {};
44762
44842
  };
44763
44843
  const kind = templateInfo.kind;
44764
44844
  const format = templateInfo.format;
44765
- const result = await buildFormTemplateData(repoPath, relativePath, stagedOnly, kind, format);
44845
+ const result = await buildFormTemplateData(relativePath, {
44846
+ kind,
44847
+ format
44848
+ }, context);
44766
44849
  if (result.ignoreResult) return result.ignoreResult;
44767
44850
  const { formData, className } = result;
44768
44851
  return handleIdBasedOperation({
@@ -44778,7 +44861,9 @@ var __webpack_exports__ = {};
44778
44861
  subPathForCodeUpdate: null
44779
44862
  });
44780
44863
  }
44781
- async function handleAssetChange(repoPath, relativePath, changeType, editorYaml, stagedOnly = false) {
44864
+ async function handleAssetChange(change, context) {
44865
+ const { repoPath, editorYaml, stagedOnly = false } = context;
44866
+ const { relativePath, changeType } = change;
44782
44867
  const assetPath = relativePath.replace(/^theme[\/\\]assets[\/\\]/, "");
44783
44868
  const fileBuffer = await readBinaryFileContent(repoPath, relativePath, stagedOnly);
44784
44869
  const base64Content = fileBuffer.toString("base64");
@@ -45205,7 +45290,15 @@ var __webpack_exports__ = {};
45205
45290
  originalFilePaths.push(change.path);
45206
45291
  continue;
45207
45292
  }
45208
- const routeResult = await routeFileChange(this.config.repoPath, change.path, change.type, this.config.editorYaml, this.config.stagedOnly, change.from);
45293
+ const routeResult = await routeFileChange({
45294
+ relativePath: change.path,
45295
+ changeType: change.type,
45296
+ fromPath: change.from
45297
+ }, {
45298
+ repoPath: this.config.repoPath,
45299
+ editorYaml: this.config.editorYaml,
45300
+ stagedOnly: this.config.stagedOnly
45301
+ });
45209
45302
  const results = Array.isArray(routeResult) ? routeResult : [
45210
45303
  routeResult
45211
45304
  ];
@@ -45392,7 +45485,15 @@ var __webpack_exports__ = {};
45392
45485
  const newSaveArray = [];
45393
45486
  const newFilePaths = [];
45394
45487
  for (const change of changes){
45395
- const routeResult = await routeFileChange(this.config.repoPath, change.path, change.type, this.config.editorYaml, this.config.stagedOnly, change.from);
45488
+ const routeResult = await routeFileChange({
45489
+ relativePath: change.path,
45490
+ changeType: change.type,
45491
+ fromPath: change.from
45492
+ }, {
45493
+ repoPath: this.config.repoPath,
45494
+ editorYaml: this.config.editorYaml,
45495
+ stagedOnly: this.config.stagedOnly
45496
+ });
45396
45497
  const results = Array.isArray(routeResult) ? routeResult : [
45397
45498
  routeResult
45398
45499
  ];
@@ -45790,6 +45891,12 @@ var __webpack_exports__ = {};
45790
45891
  this.startLocalChangeFallbackPolling();
45791
45892
  await new Promise(()=>{});
45792
45893
  }
45894
+ startWatchingInBackground(onError) {
45895
+ this.startWatching().catch((error)=>{
45896
+ this.cleanup();
45897
+ onError?.(error);
45898
+ });
45899
+ }
45793
45900
  async initializeLocalChangeFingerprint() {
45794
45901
  if (this.stagedOnly) return;
45795
45902
  try {
@@ -45926,22 +46033,28 @@ var __webpack_exports__ = {};
45926
46033
  appName
45927
46034
  };
45928
46035
  }
45929
- async function validation_validateBranchSyncStatus(git, branchName, appId, anvilUrl, username) {
46036
+ async function validation_validateBranchSyncStatus(git, branchName, options) {
46037
+ const { appId, anvilUrl, username } = options;
45930
46038
  logger_logger.verbose(chalk_source.blue("Checking branch sync status..."));
45931
46039
  let authToken;
45932
46040
  try {
45933
46041
  authToken = await auth_getValidAuthToken(anvilUrl, username);
45934
46042
  } catch (e) {
45935
- return validateViaAnvilServer(git, branchName, appId, anvilUrl, username);
46043
+ return validateViaAnvilServer(git, branchName, options);
45936
46044
  }
45937
46045
  try {
45938
- return await validateViaGitFetch(git, branchName, appId, anvilUrl, authToken);
46046
+ return await validateViaGitFetch(git, branchName, {
46047
+ appId,
46048
+ anvilUrl,
46049
+ authToken
46050
+ });
45939
46051
  } catch (e) {
45940
46052
  logger_logger.verbose(chalk_source.yellow("Git fetch failed, trying server validation..."));
45941
- return validateViaAnvilServer(git, branchName, appId, anvilUrl, username);
46053
+ return validateViaAnvilServer(git, branchName, options);
45942
46054
  }
45943
46055
  }
45944
- async function validateViaGitFetch(git, branchName, appId, anvilUrl, authToken) {
46056
+ async function validateViaGitFetch(git, branchName, options) {
46057
+ const { appId, anvilUrl, authToken } = options;
45945
46058
  const baseUrl = new URL(anvilUrl);
45946
46059
  const encodedToken = encodeURIComponent(authToken);
45947
46060
  const gitPath = `/git/${appId}.git`;
@@ -46002,7 +46115,8 @@ var __webpack_exports__ = {};
46002
46115
  throw errors_createGitError.fetchFailed(e.message);
46003
46116
  }
46004
46117
  }
46005
- async function validateViaAnvilServer(git, branchName, appId, anvilUrl, username) {
46118
+ async function validateViaAnvilServer(git, branchName, options) {
46119
+ const { appId, anvilUrl, username } = options;
46006
46120
  logger_logger.verbose(chalk_source.blue("Validating sync status with Anvil server..."));
46007
46121
  const authToken = await auth_getValidAuthToken(anvilUrl, username);
46008
46122
  let commitId;
@@ -46047,676 +46161,13 @@ var __webpack_exports__ = {};
46047
46161
  throw createNetworkError.network(e.message);
46048
46162
  }
46049
46163
  }
46050
- var external_http_ = __webpack_require__("http");
46051
- const external_readline_namespaceObject = require("readline");
46052
- var external_readline_default = /*#__PURE__*/ __webpack_require__.n(external_readline_namespaceObject);
46053
- const external_node_url_namespaceObject = require("node:url");
46054
- const external_node_child_process_namespaceObject = require("node:child_process");
46055
- let isDockerCached;
46056
- function hasDockerEnv() {
46057
- try {
46058
- external_node_fs_.statSync('/.dockerenv');
46059
- return true;
46060
- } catch {
46061
- return false;
46062
- }
46063
- }
46064
- function hasDockerCGroup() {
46065
- try {
46066
- return external_node_fs_.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
46067
- } catch {
46068
- return false;
46069
- }
46070
- }
46071
- function isDocker() {
46072
- if (void 0 === isDockerCached) isDockerCached = hasDockerEnv() || hasDockerCGroup();
46073
- return isDockerCached;
46074
- }
46075
- let cachedResult;
46076
- const hasContainerEnv = ()=>{
46077
- try {
46078
- external_node_fs_.statSync('/run/.containerenv');
46079
- return true;
46080
- } catch {
46081
- return false;
46082
- }
46083
- };
46084
- function isInsideContainer() {
46085
- if (void 0 === cachedResult) cachedResult = hasContainerEnv() || isDocker();
46086
- return cachedResult;
46087
- }
46088
- const isWsl = ()=>{
46089
- if ('linux' !== external_node_process_namespaceObject.platform) return false;
46090
- if (external_node_os_namespaceObject.release().toLowerCase().includes('microsoft')) {
46091
- if (isInsideContainer()) return false;
46092
- return true;
46093
- }
46094
- try {
46095
- return external_node_fs_.readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft') ? !isInsideContainer() : false;
46096
- } catch {
46097
- return false;
46098
- }
46099
- };
46100
- const is_wsl = external_node_process_namespaceObject.env.__IS_WSL_TEST__ ? isWsl : isWsl();
46101
- const wslDrivesMountPoint = (()=>{
46102
- const defaultMountPoint = '/mnt/';
46103
- let mountPoint;
46104
- return async function() {
46105
- if (mountPoint) return mountPoint;
46106
- const configFilePath = '/etc/wsl.conf';
46107
- let isConfigFileExists = false;
46108
- try {
46109
- await external_node_fs_promises_namespaceObject.access(configFilePath, external_node_fs_promises_namespaceObject.constants.F_OK);
46110
- isConfigFileExists = true;
46111
- } catch {}
46112
- if (!isConfigFileExists) return defaultMountPoint;
46113
- const configContent = await external_node_fs_promises_namespaceObject.readFile(configFilePath, {
46114
- encoding: 'utf8'
46115
- });
46116
- const configMountPoint = /(?<!#.*)root\s*=\s*(?<mountPoint>.*)/g.exec(configContent);
46117
- if (!configMountPoint) return defaultMountPoint;
46118
- mountPoint = configMountPoint.groups.mountPoint.trim();
46119
- mountPoint = mountPoint.endsWith('/') ? mountPoint : `${mountPoint}/`;
46120
- return mountPoint;
46121
- };
46122
- })();
46123
- const powerShellPathFromWsl = async ()=>{
46124
- const mountPoint = await wslDrivesMountPoint();
46125
- return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
46126
- };
46127
- const powerShellPath = async ()=>{
46128
- if (is_wsl) return powerShellPathFromWsl();
46129
- return `${external_node_process_namespaceObject.env.SYSTEMROOT || external_node_process_namespaceObject.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
46130
- };
46131
- function defineLazyProperty(object, propertyName, valueGetter) {
46132
- const define = (value)=>Object.defineProperty(object, propertyName, {
46133
- value,
46134
- enumerable: true,
46135
- writable: true
46136
- });
46137
- Object.defineProperty(object, propertyName, {
46138
- configurable: true,
46139
- enumerable: true,
46140
- get () {
46141
- const result = valueGetter();
46142
- define(result);
46143
- return result;
46144
- },
46145
- set (value) {
46146
- define(value);
46147
- }
46148
- });
46149
- return object;
46150
- }
46151
- const execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_namespaceObject.execFile);
46152
- async function defaultBrowserId() {
46153
- if ('darwin' !== external_node_process_namespaceObject.platform) throw new Error('macOS only');
46154
- const { stdout } = await execFileAsync('defaults', [
46155
- 'read',
46156
- 'com.apple.LaunchServices/com.apple.launchservices.secure',
46157
- 'LSHandlers'
46158
- ]);
46159
- const match = /LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(stdout);
46160
- const browserId = match?.groups.id ?? 'com.apple.Safari';
46161
- if ('com.apple.safari' === browserId) return 'com.apple.Safari';
46162
- return browserId;
46163
- }
46164
- const run_applescript_execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_namespaceObject.execFile);
46165
- async function runAppleScript(script, { humanReadableOutput = true, signal } = {}) {
46166
- if ('darwin' !== external_node_process_namespaceObject.platform) throw new Error('macOS only');
46167
- const outputArguments = humanReadableOutput ? [] : [
46168
- '-ss'
46169
- ];
46170
- const execOptions = {};
46171
- if (signal) execOptions.signal = signal;
46172
- const { stdout } = await run_applescript_execFileAsync("osascript", [
46173
- '-e',
46174
- script,
46175
- outputArguments
46176
- ], execOptions);
46177
- return stdout.trim();
46178
- }
46179
- async function bundleName(bundleId) {
46180
- 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")`);
46181
- }
46182
- const windows_execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_namespaceObject.execFile);
46183
- const windowsBrowserProgIds = {
46184
- MSEdgeHTM: {
46185
- name: 'Edge',
46186
- id: 'com.microsoft.edge'
46187
- },
46188
- MSEdgeBHTML: {
46189
- name: 'Edge Beta',
46190
- id: 'com.microsoft.edge.beta'
46191
- },
46192
- MSEdgeDHTML: {
46193
- name: 'Edge Dev',
46194
- id: 'com.microsoft.edge.dev'
46195
- },
46196
- AppXq0fevzme2pys62n3e0fbqa7peapykr8v: {
46197
- name: 'Edge',
46198
- id: 'com.microsoft.edge.old'
46199
- },
46200
- ChromeHTML: {
46201
- name: 'Chrome',
46202
- id: 'com.google.chrome'
46203
- },
46204
- ChromeBHTML: {
46205
- name: 'Chrome Beta',
46206
- id: 'com.google.chrome.beta'
46207
- },
46208
- ChromeDHTML: {
46209
- name: 'Chrome Dev',
46210
- id: 'com.google.chrome.dev'
46211
- },
46212
- ChromiumHTM: {
46213
- name: 'Chromium',
46214
- id: 'org.chromium.Chromium'
46215
- },
46216
- BraveHTML: {
46217
- name: 'Brave',
46218
- id: 'com.brave.Browser'
46219
- },
46220
- BraveBHTML: {
46221
- name: 'Brave Beta',
46222
- id: 'com.brave.Browser.beta'
46223
- },
46224
- BraveDHTML: {
46225
- name: 'Brave Dev',
46226
- id: 'com.brave.Browser.dev'
46227
- },
46228
- BraveSSHTM: {
46229
- name: 'Brave Nightly',
46230
- id: 'com.brave.Browser.nightly'
46231
- },
46232
- FirefoxURL: {
46233
- name: 'Firefox',
46234
- id: 'org.mozilla.firefox'
46235
- },
46236
- OperaStable: {
46237
- name: 'Opera',
46238
- id: 'com.operasoftware.Opera'
46239
- },
46240
- VivaldiHTM: {
46241
- name: 'Vivaldi',
46242
- id: 'com.vivaldi.Vivaldi'
46243
- },
46244
- 'IE.HTTP': {
46245
- name: 'Internet Explorer',
46246
- id: 'com.microsoft.ie'
46247
- }
46248
- };
46249
- new Map(Object.entries(windowsBrowserProgIds));
46250
- class UnknownBrowserError extends Error {
46251
- }
46252
- async function defaultBrowser(_execFileAsync = windows_execFileAsync) {
46253
- const { stdout } = await _execFileAsync('reg', [
46254
- 'QUERY',
46255
- ' HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice',
46256
- '/v',
46257
- 'ProgId'
46258
- ]);
46259
- const match = /ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(stdout);
46260
- if (!match) throw new UnknownBrowserError(`Cannot find Windows browser in stdout: ${JSON.stringify(stdout)}`);
46261
- const { id } = match.groups;
46262
- const browser = windowsBrowserProgIds[id];
46263
- if (!browser) throw new UnknownBrowserError(`Unknown browser ID: ${id}`);
46264
- return browser;
46265
- }
46266
- const default_browser_execFileAsync = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_namespaceObject.execFile);
46267
- const titleize = (string)=>string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x)=>x.toUpperCase());
46268
- async function default_browser_defaultBrowser() {
46269
- if ('darwin' === external_node_process_namespaceObject.platform) {
46270
- const id = await defaultBrowserId();
46271
- const name = await bundleName(id);
46272
- return {
46273
- name,
46274
- id
46275
- };
46276
- }
46277
- if ('linux' === external_node_process_namespaceObject.platform) {
46278
- const { stdout } = await default_browser_execFileAsync('xdg-mime', [
46279
- 'query',
46280
- 'default',
46281
- 'x-scheme-handler/http'
46282
- ]);
46283
- const id = stdout.trim();
46284
- const name = titleize(id.replace(/.desktop$/, '').replace('-', ' '));
46285
- return {
46286
- name,
46287
- id
46288
- };
46289
- }
46290
- if ('win32' === external_node_process_namespaceObject.platform) return defaultBrowser();
46291
- throw new Error('Only macOS, Linux, and Windows are supported');
46292
- }
46293
- const execFile = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_namespaceObject.execFile);
46294
- const open_dirname = external_node_path_.dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
46295
- const localXdgOpenPath = external_node_path_.join(open_dirname, 'xdg-open');
46296
- const { platform: open_platform, arch } = external_node_process_namespaceObject;
46297
- async function getWindowsDefaultBrowserFromWsl() {
46298
- const powershellPath = await powerShellPath();
46299
- const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
46300
- const encodedCommand = external_node_buffer_namespaceObject.Buffer.from(rawCommand, 'utf16le').toString('base64');
46301
- const { stdout } = await execFile(powershellPath, [
46302
- '-NoProfile',
46303
- '-NonInteractive',
46304
- '-ExecutionPolicy',
46305
- 'Bypass',
46306
- '-EncodedCommand',
46307
- encodedCommand
46308
- ], {
46309
- encoding: 'utf8'
46310
- });
46311
- const progId = stdout.trim();
46312
- const browserMap = {
46313
- ChromeHTML: 'com.google.chrome',
46314
- BraveHTML: 'com.brave.Browser',
46315
- MSEdgeHTM: 'com.microsoft.edge',
46316
- FirefoxURL: 'org.mozilla.firefox'
46317
- };
46318
- return browserMap[progId] ? {
46319
- id: browserMap[progId]
46320
- } : {};
46321
- }
46322
- const pTryEach = async (array, mapper)=>{
46323
- let latestError;
46324
- for (const item of array)try {
46325
- return await mapper(item);
46326
- } catch (error) {
46327
- latestError = error;
46328
- }
46329
- throw latestError;
46330
- };
46331
- const baseOpen = async (options)=>{
46332
- options = {
46333
- wait: false,
46334
- background: false,
46335
- newInstance: false,
46336
- allowNonzeroExitCode: false,
46337
- ...options
46338
- };
46339
- if (Array.isArray(options.app)) return pTryEach(options.app, (singleApp)=>baseOpen({
46340
- ...options,
46341
- app: singleApp
46342
- }));
46343
- let { name: app, arguments: appArguments = [] } = options.app ?? {};
46344
- appArguments = [
46345
- ...appArguments
46346
- ];
46347
- if (Array.isArray(app)) return pTryEach(app, (appName)=>baseOpen({
46348
- ...options,
46349
- app: {
46350
- name: appName,
46351
- arguments: appArguments
46352
- }
46353
- }));
46354
- if ('browser' === app || 'browserPrivate' === app) {
46355
- const ids = {
46356
- 'com.google.chrome': 'chrome',
46357
- 'google-chrome.desktop': 'chrome',
46358
- 'com.brave.Browser': 'brave',
46359
- 'org.mozilla.firefox': 'firefox',
46360
- 'firefox.desktop': 'firefox',
46361
- 'com.microsoft.msedge': 'edge',
46362
- 'com.microsoft.edge': 'edge',
46363
- 'com.microsoft.edgemac': 'edge',
46364
- 'microsoft-edge.desktop': 'edge'
46365
- };
46366
- const flags = {
46367
- chrome: '--incognito',
46368
- brave: '--incognito',
46369
- firefox: '--private-window',
46370
- edge: '--inPrivate'
46371
- };
46372
- const browser = is_wsl ? await getWindowsDefaultBrowserFromWsl() : await default_browser_defaultBrowser();
46373
- if (browser.id in ids) {
46374
- const browserName = ids[browser.id];
46375
- if ('browserPrivate' === app) appArguments.push(flags[browserName]);
46376
- return baseOpen({
46377
- ...options,
46378
- app: {
46379
- name: open_apps[browserName],
46380
- arguments: appArguments
46381
- }
46382
- });
46383
- }
46384
- throw new Error(`${browser.name} is not supported as a default browser`);
46385
- }
46386
- let command;
46387
- const cliArguments = [];
46388
- const childProcessOptions = {};
46389
- if ('darwin' === open_platform) {
46390
- command = 'open';
46391
- if (options.wait) cliArguments.push('--wait-apps');
46392
- if (options.background) cliArguments.push('--background');
46393
- if (options.newInstance) cliArguments.push('--new');
46394
- if (app) cliArguments.push('-a', app);
46395
- } else if ('win32' !== open_platform && (!is_wsl || isInsideContainer() || app)) {
46396
- if (app) command = app;
46397
- else {
46398
- const isBundled = !open_dirname || '/' === open_dirname;
46399
- let exeLocalXdgOpen = false;
46400
- try {
46401
- await external_node_fs_promises_namespaceObject.access(localXdgOpenPath, external_node_fs_promises_namespaceObject.constants.X_OK);
46402
- exeLocalXdgOpen = true;
46403
- } catch {}
46404
- const useSystemXdgOpen = external_node_process_namespaceObject.versions.electron ?? ('android' === open_platform || isBundled || !exeLocalXdgOpen);
46405
- command = useSystemXdgOpen ? 'xdg-open' : localXdgOpenPath;
46406
- }
46407
- if (appArguments.length > 0) cliArguments.push(...appArguments);
46408
- if (!options.wait) {
46409
- childProcessOptions.stdio = 'ignore';
46410
- childProcessOptions.detached = true;
46411
- }
46412
- } else {
46413
- command = await powerShellPath();
46414
- cliArguments.push('-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-EncodedCommand');
46415
- if (!is_wsl) childProcessOptions.windowsVerbatimArguments = true;
46416
- const encodedArguments = [
46417
- 'Start'
46418
- ];
46419
- if (options.wait) encodedArguments.push('-Wait');
46420
- if (app) {
46421
- encodedArguments.push(`"\`"${app}\`""`);
46422
- if (options.target) appArguments.push(options.target);
46423
- } else if (options.target) encodedArguments.push(`"${options.target}"`);
46424
- if (appArguments.length > 0) {
46425
- appArguments = appArguments.map((argument)=>`"\`"${argument}\`""`);
46426
- encodedArguments.push('-ArgumentList', appArguments.join(','));
46427
- }
46428
- options.target = external_node_buffer_namespaceObject.Buffer.from(encodedArguments.join(' '), 'utf16le').toString('base64');
46429
- }
46430
- if ('darwin' === open_platform && appArguments.length > 0) cliArguments.push('--args', ...appArguments);
46431
- if (options.target) cliArguments.push(options.target);
46432
- const subprocess = external_node_child_process_namespaceObject.spawn(command, cliArguments, childProcessOptions);
46433
- if (options.wait) return new Promise((resolve, reject)=>{
46434
- subprocess.once('error', reject);
46435
- subprocess.once('close', (exitCode)=>{
46436
- if (!options.allowNonzeroExitCode && exitCode > 0) return void reject(new Error(`Exited with code ${exitCode}`));
46437
- resolve(subprocess);
46438
- });
46439
- });
46440
- subprocess.unref();
46441
- return subprocess;
46442
- };
46443
- const open_open = (target, options)=>{
46444
- if ('string' != typeof target) throw new TypeError('Expected a `target`');
46445
- return baseOpen({
46446
- ...options,
46447
- target
46448
- });
46449
- };
46450
- function detectArchBinary(binary) {
46451
- if ('string' == typeof binary || Array.isArray(binary)) return binary;
46452
- const { [arch]: archBinary } = binary;
46453
- if (!archBinary) throw new Error(`${arch} is not supported`);
46454
- return archBinary;
46455
- }
46456
- function detectPlatformBinary({ [open_platform]: platformBinary }, { wsl }) {
46457
- if (wsl && is_wsl) return detectArchBinary(wsl);
46458
- if (!platformBinary) throw new Error(`${open_platform} is not supported`);
46459
- return detectArchBinary(platformBinary);
46460
- }
46461
- const open_apps = {};
46462
- defineLazyProperty(open_apps, 'chrome', ()=>detectPlatformBinary({
46463
- darwin: 'google chrome',
46464
- win32: 'chrome',
46465
- linux: [
46466
- 'google-chrome',
46467
- 'google-chrome-stable',
46468
- 'chromium'
46469
- ]
46470
- }, {
46471
- wsl: {
46472
- ia32: '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe',
46473
- x64: [
46474
- '/mnt/c/Program Files/Google/Chrome/Application/chrome.exe',
46475
- '/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe'
46476
- ]
46477
- }
46478
- }));
46479
- defineLazyProperty(open_apps, 'brave', ()=>detectPlatformBinary({
46480
- darwin: 'brave browser',
46481
- win32: 'brave',
46482
- linux: [
46483
- 'brave-browser',
46484
- 'brave'
46485
- ]
46486
- }, {
46487
- wsl: {
46488
- ia32: '/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe',
46489
- x64: [
46490
- '/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe',
46491
- '/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe'
46492
- ]
46493
- }
46494
- }));
46495
- defineLazyProperty(open_apps, 'firefox', ()=>detectPlatformBinary({
46496
- darwin: 'firefox',
46497
- win32: String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,
46498
- linux: 'firefox'
46499
- }, {
46500
- wsl: '/mnt/c/Program Files/Mozilla Firefox/firefox.exe'
46501
- }));
46502
- defineLazyProperty(open_apps, 'edge', ()=>detectPlatformBinary({
46503
- darwin: 'microsoft edge',
46504
- win32: 'msedge',
46505
- linux: [
46506
- 'microsoft-edge',
46507
- 'microsoft-edge-dev'
46508
- ]
46509
- }, {
46510
- wsl: '/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe'
46511
- }));
46512
- defineLazyProperty(open_apps, 'browser', ()=>'browser');
46513
- defineLazyProperty(open_apps, 'browserPrivate', ()=>'browserPrivate');
46514
- const node_modules_open = open_open;
46515
- const successPage = `<!DOCTYPE html>
46516
- <html lang="en">
46517
- <head>
46518
- <meta charset="utf-8" />
46519
- <meta name="viewport" content="width=device-width, initial-scale=1" />
46520
- <title>Anvil Sync • Login Complete</title>
46521
- <link rel="preconnect" href="https://fonts.googleapis.com">
46522
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
46523
- <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
46524
- <style>
46525
- * { box-sizing: border-box; }
46526
- html, body { height: 100%; margin: 0; }
46527
- body {
46528
- font-family: Poppins, -apple-system, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
46529
- color: #555555;
46530
- background: #f7fdff;
46531
- display: flex;
46532
- align-items: center;
46533
- justify-content: center;
46534
- padding: 20px;
46535
- }
46536
- .card {
46537
- width: min(480px, 100%);
46538
- background: #ffffff;
46539
- border-radius: 12px;
46540
- padding: 48px 40px;
46541
- text-align: center;
46542
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
46543
- }
46544
- .icon {
46545
- display: inline-flex;
46546
- align-items: center;
46547
- justify-content: center;
46548
- width: 56px;
46549
- height: 56px;
46550
- margin: 0 auto 24px;
46551
- border-radius: 50%;
46552
- background: #1bb0ee;
46553
- color: white;
46554
- }
46555
- .icon svg {
46556
- width: 28px;
46557
- height: 28px;
46558
- }
46559
- h1 {
46560
- font-size: 24px;
46561
- font-weight: 600;
46562
- line-height: 1.3;
46563
- margin: 0 0 12px;
46564
- color: #1a1a1a;
46565
- }
46566
- p {
46567
- color: #555555;
46568
- font-size: 15px;
46569
- line-height: 1.5;
46570
- margin: 0;
46571
- }
46572
- </style>
46573
- </head>
46574
- <body>
46575
- <main class="card" role="status" aria-live="polite">
46576
- <div class="icon" aria-hidden="true">
46577
- <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
46578
- <path d="M20 7L9 18l-5-5" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
46579
- </svg>
46580
- </div>
46581
- <h1>Anvil login complete</h1>
46582
- <p>Close this window and return to your terminal to continue.</p>
46583
- </main>
46584
- </body>
46585
- </html>`;
46586
- function errorPage(errorMsg) {
46587
- return `<!DOCTYPE html>
46588
- <html lang="en">
46589
- <head>
46590
- <meta charset="utf-8" />
46591
- <meta name="viewport" content="width=device-width, initial-scale=1" />
46592
- <title>Anvil Sync • Login Error</title>
46593
- <link rel="preconnect" href="https://fonts.googleapis.com">
46594
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
46595
- <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
46596
- <style>
46597
- * { box-sizing: border-box; }
46598
- html, body { height: 100%; margin: 0; }
46599
- body {
46600
- font-family: Poppins, -apple-system, system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
46601
- color: #555555;
46602
- background: #f7fdff;
46603
- display: flex;
46604
- align-items: center;
46605
- justify-content: center;
46606
- padding: 20px;
46607
- }
46608
- .card {
46609
- width: min(480px, 100%);
46610
- background: #ffffff;
46611
- border-radius: 12px;
46612
- padding: 48px 40px;
46613
- text-align: center;
46614
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
46615
- }
46616
- .icon {
46617
- display: inline-flex;
46618
- align-items: center;
46619
- justify-content: center;
46620
- width: 56px;
46621
- height: 56px;
46622
- margin: 0 auto 24px;
46623
- border-radius: 50%;
46624
- background: #ef4444;
46625
- color: white;
46626
- }
46627
- .icon svg {
46628
- width: 28px;
46629
- height: 28px;
46630
- }
46631
- h1 {
46632
- font-size: 24px;
46633
- font-weight: 600;
46634
- line-height: 1.3;
46635
- margin: 0 0 16px;
46636
- color: #1a1a1a;
46637
- }
46638
- p {
46639
- color: #555555;
46640
- font-size: 15px;
46641
- line-height: 1.5;
46642
- margin: 16px 0 0;
46643
- }
46644
- .details {
46645
- color: #666666;
46646
- font-size: 13px;
46647
- word-break: break-word;
46648
- font-weight: 500;
46649
- font-family: ui-monospace, "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace;
46650
- margin: 16px 0 0;
46651
- padding: 12px;
46652
- background: #f8f9fa;
46653
- border-radius: 6px;
46654
- text-align: left;
46655
- }
46656
- </style>
46657
- </head>
46658
- <body>
46659
- <main class="card" role="status" aria-live="polite">
46660
- <div class="icon" aria-hidden="true">
46661
- <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
46662
- <path d="M15 9l-6 6M9 9l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
46663
- </svg>
46664
- </div>
46665
- <h1>Anvil login failed</h1>
46666
- <div id="details" class="details">${errorMsg}</div>
46667
- <p>Close this window and return to your terminal to retry.</p>
46668
- </main>
46669
- </body>
46670
- </html>`;
46671
- }
46672
- const CLIENT_ID = "anvil-sync";
46164
+ __webpack_require__("http");
46165
+ require("readline");
46166
+ const CLIENT_ID = ANVIL_SYNC_CLIENT_ID;
46673
46167
  const SCOPES = "apps:read apps:write user:read";
46674
- function oauth_login_base64url(buf) {
46675
- return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
46676
- }
46677
46168
  function sleep(ms) {
46678
46169
  return new Promise((resolve)=>setTimeout(resolve, ms));
46679
46170
  }
46680
- function createBrowserLaunchPrompt(authUrl) {
46681
- if (!process.stdin.isTTY || !process.stdout.isTTY) return {
46682
- waitForOpen: Promise.resolve(false),
46683
- close: ()=>{}
46684
- };
46685
- const rl = external_readline_namespaceObject.createInterface({
46686
- input: process.stdin,
46687
- output: process.stdout
46688
- });
46689
- let closed = false;
46690
- let resolveWait = null;
46691
- const close = (opened = false)=>{
46692
- if (closed) return;
46693
- closed = true;
46694
- rl.close();
46695
- resolveWait?.(opened);
46696
- resolveWait = null;
46697
- };
46698
- const waitForOpen = new Promise((resolve)=>{
46699
- resolveWait = resolve;
46700
- rl.on("SIGINT", ()=>{
46701
- close();
46702
- process.kill(process.pid, "SIGINT");
46703
- });
46704
- rl.question("", async ()=>{
46705
- try {
46706
- await node_modules_open(authUrl);
46707
- logger_logger.info(chalk_source.dim("Opened your browser to continue login."));
46708
- close(true);
46709
- } catch {
46710
- logger_logger.warn("Could not open a browser automatically.");
46711
- close(false);
46712
- }
46713
- });
46714
- });
46715
- return {
46716
- waitForOpen,
46717
- close
46718
- };
46719
- }
46720
46171
  async function parseOAuthError(response) {
46721
46172
  const contentType = response.headers.get("content-type") || "";
46722
46173
  if (contentType.includes("application/json")) {
@@ -46732,23 +46183,6 @@ var __webpack_exports__ = {};
46732
46183
  return text;
46733
46184
  }
46734
46185
  }
46735
- async function exchangeAuthorizationCodeForTokens(anvilUrl, redirectUri, code, codeVerifier) {
46736
- const tokenResponse = await fetch(`${anvilUrl}/oauth/token`, {
46737
- method: "POST",
46738
- headers: {
46739
- "Content-Type": "application/x-www-form-urlencoded"
46740
- },
46741
- body: new URLSearchParams({
46742
- grant_type: "authorization_code",
46743
- code,
46744
- redirect_uri: redirectUri,
46745
- client_id: CLIENT_ID,
46746
- code_verifier: codeVerifier
46747
- })
46748
- });
46749
- if (!tokenResponse.ok) throw new Error(`Failed to exchange authorization code for token. ${await parseOAuthError(tokenResponse)}`);
46750
- return await tokenResponse.json();
46751
- }
46752
46186
  async function requestDeviceAuthorization(anvilUrl) {
46753
46187
  const response = await fetch(`${anvilUrl}/oauth/device_authorization`, {
46754
46188
  method: "POST",
@@ -46796,131 +46230,6 @@ var __webpack_exports__ = {};
46796
46230
  }
46797
46231
  throw new Error("Device login expired before it was approved.");
46798
46232
  }
46799
- async function createPkceLoginFlow(anvilUrl) {
46800
- const codeVerifier = external_crypto_.randomBytes(48).toString("hex");
46801
- const codeChallenge = oauth_login_base64url(external_crypto_.createHash("sha256").update(codeVerifier, "ascii").digest());
46802
- const state = external_crypto_.randomBytes(16).toString("hex");
46803
- const server = external_http_.createServer();
46804
- await new Promise((resolve)=>server.listen(0, "127.0.0.1", resolve));
46805
- const address = server.address();
46806
- if (!address || "string" == typeof address) throw new Error("No address");
46807
- const port = address.port;
46808
- const redirectUri = `http://127.0.0.1:${port}/oauth-callback`;
46809
- const authUrl = new URL(`${anvilUrl}/oauth/authorize`);
46810
- authUrl.searchParams.set("response_type", "code");
46811
- authUrl.searchParams.set("client_id", CLIENT_ID);
46812
- authUrl.searchParams.set("redirect_uri", redirectUri);
46813
- authUrl.searchParams.set("scope", SCOPES);
46814
- authUrl.searchParams.set("state", state);
46815
- authUrl.searchParams.set("code_challenge", codeChallenge);
46816
- authUrl.searchParams.set("code_challenge_method", "S256");
46817
- const codePromise = new Promise((resolve, reject)=>{
46818
- server.on("request", (req, res)=>{
46819
- if (!req.url) return;
46820
- const url = new URL(req.url, `http://127.0.0.1:${port}`);
46821
- if ("/oauth-callback" !== url.pathname) return;
46822
- const code = url.searchParams.get("code") || void 0;
46823
- const error = url.searchParams.get("error") || void 0;
46824
- const recvState = url.searchParams.get("state");
46825
- if (!recvState || !code && !error) {
46826
- res.statusCode = 400;
46827
- res.end("Missing code, error or state");
46828
- reject(new Error("Missing code/state/error"));
46829
- server.close();
46830
- return;
46831
- }
46832
- res.statusCode = 200;
46833
- res.setHeader("Content-Type", "text/html; charset=utf-8");
46834
- if (code) res.end(successPage);
46835
- else res.end(errorPage(error || "unknown"));
46836
- resolve({
46837
- code,
46838
- error,
46839
- recvState
46840
- });
46841
- server.closeAllConnections();
46842
- server.close();
46843
- });
46844
- });
46845
- let closed = false;
46846
- server.on("close", ()=>{
46847
- closed = true;
46848
- });
46849
- const close = async ()=>{
46850
- if (closed) return;
46851
- closed = true;
46852
- server.closeAllConnections();
46853
- if (!server.listening) return;
46854
- await new Promise((resolve)=>server.close(()=>resolve()));
46855
- };
46856
- return {
46857
- authUrl,
46858
- close,
46859
- waitForLogin: (async ()=>{
46860
- const { code, error, recvState } = await codePromise;
46861
- if (recvState !== state) throw new Error("Invalid state received from OAuth callback");
46862
- if (error) throw new Error(`Error received from OAuth callback: ${error}`);
46863
- const tokenData = await exchangeAuthorizationCodeForTokens(anvilUrl, redirectUri, code, codeVerifier);
46864
- return login(anvilUrl, {
46865
- access_token: tokenData.access_token,
46866
- refresh_token: tokenData.refresh_token,
46867
- expires_in: tokenData.expires_in,
46868
- scope: tokenData.scope
46869
- });
46870
- })()
46871
- };
46872
- }
46873
- function raceLoginAttempts(attempts) {
46874
- return new Promise((resolve, reject)=>{
46875
- let remaining = attempts.length;
46876
- let lastError = null;
46877
- for (const attempt of attempts)attempt.then(resolve).catch((error)=>{
46878
- if ("cancelled" === error.message) return;
46879
- remaining -= 1;
46880
- lastError = error;
46881
- if (0 === remaining && lastError) reject(lastError);
46882
- });
46883
- });
46884
- }
46885
- async function runInteractiveLoginFlow(anvilUrl) {
46886
- const pkceFlow = await createPkceLoginFlow(anvilUrl);
46887
- const deviceAuth = await requestDeviceAuthorization(anvilUrl);
46888
- const browserPrompt = createBrowserLaunchPrompt(pkceFlow.authUrl.toString());
46889
- let settled = false;
46890
- let spinnerStarted = false;
46891
- logger_logger.info(chalk_source.dim(`Logging in to ${anvilUrl}`));
46892
- console.log();
46893
- logger_logger.info(chalk_source.dim("Visit:"), `${deviceAuth.verification_uri_complete || deviceAuth.verification_uri}`);
46894
- logger_logger.info(chalk_source.dim("Device code:"), `${deviceAuth.user_code}`);
46895
- console.log();
46896
- logger_logger.info("OR Press ENTER to open a browser...");
46897
- browserPrompt.waitForOpen.then((opened)=>{
46898
- if (opened && !settled) {
46899
- spinnerStarted = true;
46900
- logger_logger.progress("login", "Waiting for login to complete...");
46901
- }
46902
- });
46903
- try {
46904
- const result = await raceLoginAttempts([
46905
- pkceFlow.waitForLogin,
46906
- pollDeviceAuthorization(anvilUrl, deviceAuth, {
46907
- isCancelled: ()=>settled
46908
- }).then(async (tokenData)=>login(anvilUrl, {
46909
- access_token: tokenData.access_token,
46910
- refresh_token: tokenData.refresh_token,
46911
- expires_in: tokenData.expires_in,
46912
- scope: tokenData.scope
46913
- }))
46914
- ]);
46915
- settled = true;
46916
- return result;
46917
- } finally{
46918
- settled = true;
46919
- browserPrompt.close();
46920
- if (spinnerStarted) logger_logger.progressEnd("login");
46921
- await pkceFlow.close();
46922
- }
46923
- }
46924
46233
  function getUrlConfigKey(appId) {
46925
46234
  return `anvil.auth.${appId}.url`;
46926
46235
  }
@@ -47034,539 +46343,6 @@ var __webpack_exports__ = {};
47034
46343
  cleanRemoteUrl
47035
46344
  };
47036
46345
  }
47037
- const defaultDeps = {
47038
- openSystem: async (pathToOpen)=>node_modules_open(pathToOpen),
47039
- isCommandAvailable: isCommandAvailable,
47040
- spawnShellCommand: async (commandLine)=>{
47041
- await new Promise((resolve, reject)=>{
47042
- const child = (0, external_child_process_.spawn)(commandLine, {
47043
- shell: true,
47044
- stdio: "inherit"
47045
- });
47046
- child.on("error", reject);
47047
- child.on("exit", (code)=>{
47048
- if (0 === code || null === code) resolve();
47049
- else reject(new Error(`Editor command exited with code ${code}`));
47050
- });
47051
- });
47052
- }
47053
- };
47054
- function parseCommandTokens(command) {
47055
- const input = command.trim();
47056
- if (!input) return [];
47057
- const tokens = [];
47058
- let current = "";
47059
- let quote = null;
47060
- let escaping = false;
47061
- for(let i = 0; i < input.length; i += 1){
47062
- const ch = input[i];
47063
- if (escaping) {
47064
- current += ch;
47065
- escaping = false;
47066
- continue;
47067
- }
47068
- if ("\\" === ch) {
47069
- escaping = true;
47070
- continue;
47071
- }
47072
- if (quote) {
47073
- if (ch === quote) quote = null;
47074
- else current += ch;
47075
- continue;
47076
- }
47077
- if ('"' === ch || "'" === ch) {
47078
- quote = ch;
47079
- continue;
47080
- }
47081
- if (/\s/.test(ch)) {
47082
- if (current) {
47083
- tokens.push(current);
47084
- current = "";
47085
- }
47086
- continue;
47087
- }
47088
- current += ch;
47089
- }
47090
- if (escaping) current += "\\";
47091
- if (quote) throw new Error(`Unterminated quote in command: ${command}`);
47092
- if (current) tokens.push(current);
47093
- return tokens;
47094
- }
47095
- function quoteForPosixShell(value) {
47096
- if ("" === value) return "''";
47097
- return `'${value.replace(/'/g, "'\"'\"'")}'`;
47098
- }
47099
- function quoteForCmdShell(value) {
47100
- const escaped = value.replace(/[%^&|<>()"!]/g, "^$&");
47101
- return `"${escaped}"`;
47102
- }
47103
- function buildShellCommandLine(tokens) {
47104
- if ("win32" === process.platform) return tokens.map(quoteForCmdShell).join(" ");
47105
- return tokens.map(quoteForPosixShell).join(" ");
47106
- }
47107
- function formatFallbackEditorLabel(preferredEditorCommand) {
47108
- const trimmed = preferredEditorCommand.trim();
47109
- if (!trimmed) return "your editor";
47110
- return trimmed;
47111
- }
47112
- async function path_open_openPathInEditorOrDefault(targetPath, preferredEditorCommand, deps = defaultDeps) {
47113
- if (preferredEditorCommand) if (deps.isCommandAvailable(preferredEditorCommand)) try {
47114
- const tokens = parseCommandTokens(preferredEditorCommand);
47115
- if (0 === tokens.length) throw new Error("empty command");
47116
- await deps.spawnShellCommand(buildShellCommandLine([
47117
- ...tokens,
47118
- targetPath
47119
- ]));
47120
- return;
47121
- } catch (error) {
47122
- logger_logger.warn(`Failed to open ${formatFallbackEditorLabel(preferredEditorCommand)} automatically: ${errors_getErrorMessage(error)}.`);
47123
- }
47124
- else logger_logger.info(`Open ${formatFallbackEditorLabel(preferredEditorCommand)} to edit your app.`);
47125
- await deps.openSystem(targetPath);
47126
- }
47127
- const CHECKOUT_ERROR_VALUE = "__ERROR__";
47128
- function isAbortLikeError(error) {
47129
- if (error instanceof Error && "AbortError" === error.name) return true;
47130
- if ("object" == typeof error && null !== error) {
47131
- const maybeType = error.type;
47132
- const maybeMessage = error.message;
47133
- if ("network_error" === maybeType && "string" == typeof maybeMessage && maybeMessage.toLowerCase().includes("abort")) return true;
47134
- }
47135
- const message = errors_getErrorMessage(error).toLowerCase();
47136
- return "aborted" === message || message.includes("aborted");
47137
- }
47138
- function normalizePickerQuery(term) {
47139
- return (term || "").trim();
47140
- }
47141
- function parseNonNegativeMs(raw) {
47142
- if (null == raw) return null;
47143
- const parsed = Number(raw);
47144
- if (!Number.isFinite(parsed) || parsed < 0) return null;
47145
- return parsed;
47146
- }
47147
- function getCheckoutPickerDelayMs() {
47148
- const fromEnv = parseNonNegativeMs(process.env.ANVIL_CHECKOUT_PICKER_DELAY_MS);
47149
- if (null != fromEnv) return fromEnv;
47150
- return 0;
47151
- }
47152
- function getCheckoutPickerPaginationDelayMs() {
47153
- return getCheckoutPickerDelayMs();
47154
- }
47155
- function getCheckoutPickerMaxRows() {
47156
- const raw = process.env.ANVIL_CHECKOUT_PICKER_MAX_ROWS;
47157
- const fromEnv = null == raw ? NaN : Number(raw);
47158
- if (null != raw && Number.isFinite(fromEnv) && fromEnv >= 4) return Math.floor(fromEnv);
47159
- return 12;
47160
- }
47161
- function formatLastEdited(lastEdited) {
47162
- if (!lastEdited) return;
47163
- return chalk_source.gray(`Last edited: ${lastEdited}`);
47164
- }
47165
- function formatAppPickerLabel(app) {
47166
- const appName = app.app_name || "Unnamed App";
47167
- return `${chalk_source.cyan(appName)} ${chalk_source.gray(`(${app.app_id})`)}`;
47168
- }
47169
- async function waitForDebounce(ms, signal) {
47170
- if (ms <= 0) return;
47171
- if (signal.aborted) throw new Error("aborted");
47172
- await new Promise((resolve, reject)=>{
47173
- const timer = setTimeout(()=>{
47174
- cleanup();
47175
- resolve();
47176
- }, ms);
47177
- const onAbort = ()=>{
47178
- cleanup();
47179
- reject(new Error("aborted"));
47180
- };
47181
- const cleanup = ()=>{
47182
- clearTimeout(timer);
47183
- signal.removeEventListener("abort", onAbort);
47184
- };
47185
- signal.addEventListener("abort", onAbort, {
47186
- once: true
47187
- });
47188
- });
47189
- }
47190
- function createCheckoutPickerSource(anvilUrl, username, deps, options = {}) {
47191
- const pageSize = options.pageSize ?? 20;
47192
- const debounceMs = options.debounceMs ?? 200;
47193
- const staleTimeMs = options.staleTimeMs ?? 30000;
47194
- const maxAutoPagesPerCall = options.maxAutoPagesPerCall ?? 8;
47195
- const initialQuery = normalizePickerQuery(options.initialQuery);
47196
- const simulatedDelayMs = getCheckoutPickerDelayMs();
47197
- const paginationDelayMs = getCheckoutPickerPaginationDelayMs();
47198
- const cache = new Map();
47199
- const getState = (query)=>{
47200
- const existing = cache.get(query);
47201
- if (existing) return existing;
47202
- const created = {
47203
- items: [],
47204
- nextCursor: null,
47205
- exhausted: false,
47206
- lastError: null,
47207
- updatedAt: 0,
47208
- inFlight: null
47209
- };
47210
- cache.set(query, created);
47211
- return created;
47212
- };
47213
- const fetchPage = async (query, signal, options = {})=>{
47214
- const state = getState(query);
47215
- if (state.inFlight) return void await state.inFlight;
47216
- state.inFlight = (async ()=>{
47217
- try {
47218
- if (simulatedDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, simulatedDelayMs));
47219
- if (options.cursor && paginationDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, paginationDelayMs));
47220
- const response = await deps.listAppsForCheckout({
47221
- anvilUrl,
47222
- username,
47223
- limit: pageSize,
47224
- cursor: options.cursor,
47225
- q: query || void 0,
47226
- signal
47227
- });
47228
- if (options.reset) state.items = [
47229
- ...response.apps
47230
- ];
47231
- else state.items.push(...response.apps);
47232
- state.nextCursor = response.next_cursor;
47233
- state.exhausted = !response.next_cursor;
47234
- state.lastError = null;
47235
- state.updatedAt = Date.now();
47236
- } catch (e) {
47237
- if (!signal.aborted && !isAbortLikeError(e)) {
47238
- const message = errors_getErrorMessage(e);
47239
- state.lastError = message;
47240
- state.updatedAt = Date.now();
47241
- }
47242
- } finally{
47243
- state.inFlight = null;
47244
- }
47245
- })();
47246
- await state.inFlight;
47247
- };
47248
- const ensureLoaded = async (query, signal)=>{
47249
- const state = getState(query);
47250
- const isStale = Date.now() - state.updatedAt > staleTimeMs;
47251
- if (0 === state.items.length) {
47252
- await waitForDebounce(debounceMs, signal);
47253
- await fetchPage(query, signal, {
47254
- cursor: void 0,
47255
- reset: false
47256
- });
47257
- } else if (state.lastError) {
47258
- await waitForDebounce(debounceMs, signal);
47259
- await fetchPage(query, signal, {
47260
- cursor: void 0,
47261
- reset: true
47262
- });
47263
- } else if (isStale) {
47264
- await waitForDebounce(debounceMs, signal);
47265
- await fetchPage(query, signal, {
47266
- cursor: void 0,
47267
- reset: true
47268
- });
47269
- }
47270
- let pagesLoaded = 0;
47271
- while(state.nextCursor && pagesLoaded < maxAutoPagesPerCall){
47272
- if (signal.aborted) throw new Error("aborted");
47273
- const cursor = state.nextCursor;
47274
- await fetchPage(query, signal, {
47275
- cursor,
47276
- reset: false
47277
- });
47278
- pagesLoaded += 1;
47279
- }
47280
- };
47281
- return {
47282
- source: async (term, { signal })=>{
47283
- const query = normalizePickerQuery(term) || initialQuery;
47284
- if (signal.aborted) return [];
47285
- await ensureLoaded(query, signal);
47286
- const state = getState(query);
47287
- if (state.lastError) return [
47288
- {
47289
- name: `${chalk_source.yellow("Fetch failed")} ${chalk_source.gray(`(${state.lastError})`)}`,
47290
- value: CHECKOUT_ERROR_VALUE,
47291
- disabled: true
47292
- }
47293
- ];
47294
- const summary = state.nextCursor ? chalk_source.gray(`Loaded ${state.items.length} apps • more available`) : chalk_source.gray(`Loaded ${state.items.length} apps`);
47295
- const choices = state.items.map((app)=>({
47296
- name: formatAppPickerLabel(app),
47297
- value: app.app_id,
47298
- description: formatLastEdited(app.last_edited)
47299
- }));
47300
- choices.unshift({
47301
- name: summary,
47302
- value: CHECKOUT_ERROR_VALUE,
47303
- disabled: true
47304
- });
47305
- return choices;
47306
- }
47307
- };
47308
- }
47309
- const INLINE_SPINNER_FRAMES = [
47310
- "⠋",
47311
- "⠙",
47312
- "⠹",
47313
- "⠸",
47314
- "⠼",
47315
- "⠴",
47316
- "⠦",
47317
- "⠧",
47318
- "⠇",
47319
- "⠏"
47320
- ];
47321
- async function runCustomCheckoutPicker(anvilUrl, username, deps, initialQuery) {
47322
- if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
47323
- const pageSize = 20;
47324
- const staleTimeMs = 30000;
47325
- const debounceMs = 180;
47326
- const simulatedDelayMs = getCheckoutPickerDelayMs();
47327
- const paginationDelayMs = getCheckoutPickerPaginationDelayMs();
47328
- const maxVisibleRows = getCheckoutPickerMaxRows();
47329
- const cache = new Map();
47330
- let query = normalizePickerQuery(initialQuery);
47331
- let selectedIndex = 0;
47332
- let scrollOffset = 0;
47333
- let loading = false;
47334
- let loadingMore = false;
47335
- let done = false;
47336
- let pendingTimer = null;
47337
- let loadingRenderTimer = null;
47338
- let activeController = null;
47339
- let resolveResult = null;
47340
- const ensureState = (key)=>{
47341
- const existing = cache.get(key);
47342
- if (existing) return existing;
47343
- const created = {
47344
- items: [],
47345
- nextCursor: null,
47346
- lastError: null,
47347
- updatedAt: 0
47348
- };
47349
- cache.set(key, created);
47350
- return created;
47351
- };
47352
- const currentState = ()=>ensureState(query);
47353
- const clearScreen = ()=>{
47354
- process.stdout.write("\x1b[2J\x1b[H");
47355
- };
47356
- const visibleRows = ()=>{
47357
- const rows = process.stdout.rows || 24;
47358
- return Math.min(maxVisibleRows, Math.max(6, rows - 9));
47359
- };
47360
- const syncViewport = ()=>{
47361
- const items = currentState().items;
47362
- if (selectedIndex >= items.length) selectedIndex = Math.max(0, items.length - 1);
47363
- const height = visibleRows();
47364
- if (selectedIndex < scrollOffset) scrollOffset = selectedIndex;
47365
- else if (selectedIndex >= scrollOffset + height) scrollOffset = Math.max(0, selectedIndex - height + 1);
47366
- };
47367
- const render = ()=>{
47368
- clearScreen();
47369
- const state = currentState();
47370
- const items = state.items;
47371
- const activeQuery = query || chalk_source.gray("(all apps)");
47372
- const spinnerFrame = INLINE_SPINNER_FRAMES[Math.floor(Date.now() / 120) % INLINE_SPINNER_FRAMES.length];
47373
- 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`);
47374
- process.stdout.write(`${chalk_source.bold("Search apps by name or app ID")}\n`);
47375
- process.stdout.write(`${chalk_source.cyan("Query:")} ${activeQuery}\n`);
47376
- process.stdout.write(`${status}\n`);
47377
- if (state.lastError) process.stdout.write(`${chalk_source.red(`Fetch failed: ${state.lastError}`)}\n`);
47378
- const height = visibleRows();
47379
- const start = scrollOffset;
47380
- const end = Math.min(items.length, start + height);
47381
- if (0 !== items.length || loading || state.lastError) for(let i = start; i < end; i += 1){
47382
- const item = items[i];
47383
- const label = formatAppPickerLabel(item);
47384
- const line = i === selectedIndex ? `${chalk_source.green("❯")} ${label}` : ` ${label}`;
47385
- process.stdout.write(`${line}\n`);
47386
- }
47387
- else process.stdout.write(`${chalk_source.gray("No matches. Keep typing.")}\n`);
47388
- process.stdout.write(`\n${chalk_source.gray("↑/↓ navigate • type to search • enter select • esc/ctrl+c cancel")}\n`);
47389
- };
47390
- const fetchPage = async (key, cursor)=>{
47391
- const state = ensureState(key);
47392
- const controller = new AbortController();
47393
- if (!cursor && activeController) activeController.abort();
47394
- activeController = controller;
47395
- loading = true;
47396
- loadingMore = !!cursor;
47397
- startLoadingAnimation();
47398
- render();
47399
- try {
47400
- if (simulatedDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, simulatedDelayMs));
47401
- if (cursor && paginationDelayMs > 0) await new Promise((resolve)=>setTimeout(resolve, paginationDelayMs));
47402
- const response = await deps.listAppsForCheckout({
47403
- anvilUrl,
47404
- username,
47405
- limit: pageSize,
47406
- cursor,
47407
- q: key || void 0,
47408
- signal: controller.signal
47409
- });
47410
- const merged = cursor ? state.items.concat(response.apps) : response.apps;
47411
- cache.set(key, {
47412
- items: merged,
47413
- nextCursor: response.next_cursor,
47414
- lastError: null,
47415
- updatedAt: Date.now()
47416
- });
47417
- if (key === query) syncViewport();
47418
- } catch (e) {
47419
- if (!controller.signal.aborted && !isAbortLikeError(e)) {
47420
- const message = errors_getErrorMessage(e);
47421
- cache.set(key, {
47422
- ...state,
47423
- lastError: message,
47424
- updatedAt: Date.now()
47425
- });
47426
- }
47427
- } finally{
47428
- if (activeController === controller) activeController = null;
47429
- loading = false;
47430
- loadingMore = false;
47431
- stopLoadingAnimation();
47432
- render();
47433
- }
47434
- };
47435
- const ensureFresh = async (key)=>{
47436
- const state = ensureState(key);
47437
- const stale = Date.now() - state.updatedAt > staleTimeMs;
47438
- if (0 === state.items.length || stale || state.lastError) await fetchPage(key);
47439
- else render();
47440
- };
47441
- const maybeLoadMore = async ()=>{
47442
- const state = currentState();
47443
- if (!state.nextCursor || loading) return;
47444
- if (selectedIndex >= Math.max(0, state.items.length - 2)) await fetchPage(query, state.nextCursor || void 0);
47445
- };
47446
- const scheduleQueryFetch = ()=>{
47447
- if (pendingTimer) clearTimeout(pendingTimer);
47448
- pendingTimer = setTimeout(()=>{
47449
- pendingTimer = null;
47450
- ensureFresh(query);
47451
- }, debounceMs);
47452
- };
47453
- const startLoadingAnimation = ()=>{
47454
- if (loadingRenderTimer) return;
47455
- loadingRenderTimer = setInterval(()=>{
47456
- if (!done && loading) render();
47457
- }, 120);
47458
- };
47459
- const stopLoadingAnimation = ()=>{
47460
- if (!loadingRenderTimer) return;
47461
- clearInterval(loadingRenderTimer);
47462
- loadingRenderTimer = null;
47463
- };
47464
- const finish = (value)=>{
47465
- done = true;
47466
- if (pendingTimer) {
47467
- clearTimeout(pendingTimer);
47468
- pendingTimer = null;
47469
- }
47470
- if (activeController) {
47471
- activeController.abort();
47472
- activeController = null;
47473
- }
47474
- stopLoadingAnimation();
47475
- process.stdin.removeListener("keypress", onKeypress);
47476
- if (process.stdin.isTTY && process.stdin.setRawMode) process.stdin.setRawMode(false);
47477
- process.stdin.pause();
47478
- clearScreen();
47479
- if (resolveResult) resolveResult(value);
47480
- };
47481
- const onKeypress = (_str, key)=>{
47482
- if (done) return;
47483
- if (key.ctrl && "c" === key.name) return void finish(null);
47484
- if ("escape" === key.name) return void finish(null);
47485
- if ("return" === key.name) {
47486
- const state = currentState();
47487
- const selected = state.items[selectedIndex];
47488
- finish(selected ? selected.app_id : null);
47489
- return;
47490
- }
47491
- if ("up" === key.name) {
47492
- if (selectedIndex > 0) {
47493
- selectedIndex -= 1;
47494
- syncViewport();
47495
- render();
47496
- }
47497
- return;
47498
- }
47499
- if ("down" === key.name) {
47500
- const maxIndex = Math.max(0, currentState().items.length - 1);
47501
- if (selectedIndex < maxIndex) {
47502
- selectedIndex += 1;
47503
- syncViewport();
47504
- render();
47505
- maybeLoadMore();
47506
- }
47507
- return;
47508
- }
47509
- if ("backspace" === key.name || "delete" === key.name) {
47510
- if (query.length > 0) {
47511
- query = query.slice(0, -1);
47512
- selectedIndex = 0;
47513
- scrollOffset = 0;
47514
- render();
47515
- scheduleQueryFetch();
47516
- }
47517
- return;
47518
- }
47519
- if (!key.ctrl && !key.meta && key.sequence && 1 === key.sequence.length && key.sequence >= " ") {
47520
- query += key.sequence;
47521
- selectedIndex = 0;
47522
- scrollOffset = 0;
47523
- render();
47524
- scheduleQueryFetch();
47525
- }
47526
- };
47527
- logger_logger.pause();
47528
- try {
47529
- external_readline_default().emitKeypressEvents(process.stdin);
47530
- if (process.stdin.isTTY && process.stdin.setRawMode) process.stdin.setRawMode(true);
47531
- process.stdin.resume();
47532
- process.stdin.on("keypress", onKeypress);
47533
- await ensureFresh(query);
47534
- return await new Promise((resolve)=>{
47535
- resolveResult = resolve;
47536
- });
47537
- } finally{
47538
- logger_logger.resume();
47539
- }
47540
- }
47541
- async function selectAppForCheckout(anvilUrl, username, deps, initialQuery) {
47542
- if (!isTestMode() && "1" !== process.env.ANVIL_CHECKOUT_LEGACY_PICKER) return runCustomCheckoutPicker(anvilUrl, username, deps, initialQuery);
47543
- const picker = createCheckoutPickerSource(anvilUrl, username, deps, {
47544
- initialQuery
47545
- });
47546
- try {
47547
- const answer = await logger_logger.prompt([
47548
- {
47549
- type: "search",
47550
- name: "value",
47551
- message: "Search apps by name or app ID",
47552
- source: picker.source,
47553
- pageSize: 12,
47554
- loop: false,
47555
- instructions: {
47556
- navigation: "↑↓ navigate • type to filter",
47557
- pager: "enter select • ctrl+c cancel"
47558
- }
47559
- }
47560
- ]);
47561
- const selected = String(answer.value || "");
47562
- if (!selected || selected === CHECKOUT_ERROR_VALUE) return null;
47563
- return selected;
47564
- } catch (e) {
47565
- const err = e;
47566
- if ("ExitPromptError" === err.name || String(err.message || "").includes("User force closed")) return null;
47567
- throw e;
47568
- }
47569
- }
47570
46346
  const isUpKey = (key, keybindings = [])=>'up' === key.name || keybindings.includes('vim') && 'k' === key.name || keybindings.includes('emacs') && key.ctrl && 'p' === key.name;
47571
46347
  const isDownKey = (key, keybindings = [])=>'down' === key.name || keybindings.includes('vim') && 'j' === key.name || keybindings.includes('emacs') && key.ctrl && 'n' === key.name;
47572
46348
  const isSpaceKey = (key)=>'space' === key.name;
@@ -49976,7 +48752,7 @@ var __webpack_exports__ = {};
49976
48752
  }
49977
48753
  createPromptModule();
49978
48754
  resolveAnvilUrl();
49979
- function decideFallbackUrl(explicitUrl, availableUrls = getAvailableAnvilUrls()) {
48755
+ function watch_decideFallbackUrl(explicitUrl, availableUrls = getAvailableAnvilUrls()) {
49980
48756
  if (explicitUrl) return {
49981
48757
  source: "explicit",
49982
48758
  url: config_normalizeAnvilUrl(explicitUrl)
@@ -50003,7 +48779,6 @@ var __webpack_exports__ = {};
50003
48779
  getValidAuthToken: auth_getValidAuthToken,
50004
48780
  validateAppId: anvil_api_validateAppId,
50005
48781
  listAppsForCheckout: listAppsForCheckout,
50006
- runInteractiveLoginFlow: runInteractiveLoginFlow,
50007
48782
  clone: async (repoUrl, destinationPath, options)=>{
50008
48783
  const cloneArgs = [];
50009
48784
  if (options?.branch) cloneArgs.push("--branch", options.branch);
@@ -50016,9 +48791,6 @@ var __webpack_exports__ = {};
50016
48791
  },
50017
48792
  hardenCheckoutGitAuth: hardenCheckoutGitAuth
50018
48793
  };
50019
- function isInteractiveSession() {
50020
- return !!(process.stdin.isTTY && process.stdout.isTTY);
50021
- }
50022
48794
  function parseCheckoutInput(input) {
50023
48795
  const trimmed = input.trim();
50024
48796
  if (!trimmed) throw new Error("Input is required.");
@@ -50060,29 +48832,12 @@ var __webpack_exports__ = {};
50060
48832
  }
50061
48833
  return appId;
50062
48834
  }
50063
- async function resolveCheckoutUrl(explicitUrl, parsedUrl) {
50064
- if (explicitUrl) {
50065
- logger_logger.verbose(chalk_source.cyan("Using Anvil URL from --url: ") + chalk_source.bold(config_normalizeAnvilUrl(explicitUrl)));
50066
- return config_normalizeAnvilUrl(explicitUrl);
50067
- }
50068
- if (parsedUrl) {
50069
- logger_logger.verbose(chalk_source.cyan("Using Anvil URL from checkout input: ") + chalk_source.bold(config_normalizeAnvilUrl(parsedUrl)));
50070
- return config_normalizeAnvilUrl(parsedUrl);
50071
- }
50072
- const decision = decideFallbackUrl(void 0);
50073
- if ("available-multiple" !== decision.source) {
50074
- if (decision.url) logger_logger.verbose(chalk_source.cyan("Using configured Anvil URL: ") + chalk_source.bold(decision.url));
50075
- return decision.url;
50076
- }
50077
- const choices = decision.urls.map((url)=>({
50078
- name: url,
50079
- value: url
50080
- }));
50081
- choices.push({
50082
- name: "Cancel",
50083
- value: null
50084
- });
50085
- return logger_logger.select("Multiple logged-in Anvil URLs found. Which one would you like to use?", choices, decision.urls[0]);
48835
+ function resolveCheckoutUrlForApi(explicitUrl, parsedUrl) {
48836
+ if (explicitUrl) return config_normalizeAnvilUrl(explicitUrl);
48837
+ if (parsedUrl) return config_normalizeAnvilUrl(parsedUrl);
48838
+ const decision = watch_decideFallbackUrl(void 0);
48839
+ if ("available-multiple" === decision.source) throw new Error(`Multiple logged-in Anvil URLs found: ${decision.urls.join(", ")}. Use --url <ANVIL_URL> to choose one.`);
48840
+ return decision.url;
50086
48841
  }
50087
48842
  async function isPathInsideGitRepo(targetPath) {
50088
48843
  const resolved = external_path_default().resolve(targetPath);
@@ -50122,64 +48877,31 @@ var __webpack_exports__ = {};
50122
48877
  logger_logger.verbose(chalk_source.cyan("Checking auth token for: ") + chalk_source.bold(username ? `${username} @ ${anvilUrl}` : anvilUrl));
50123
48878
  return await deps.getValidAuthToken(anvilUrl, username);
50124
48879
  } catch (e) {
50125
- const interactive = process.stdin.isTTY && process.stdout.isTTY;
50126
- if (!interactive) throw createAuthError.required(`Not logged in to ${anvilUrl}. Run 'anvil login ${anvilUrl}' and retry.`);
50127
- const shouldLogin = await logger_logger.confirm(`Not logged in to ${anvilUrl}. Log in now?`, true);
50128
- if (!shouldLogin) throw createAuthError.required(`Not logged in to ${anvilUrl}. Run 'anvil login ${anvilUrl}' and retry.`);
50129
- await deps.runInteractiveLoginFlow(anvilUrl);
50130
- return deps.getValidAuthToken(anvilUrl, username);
48880
+ throw createAuthError.required(`Not logged in to ${anvilUrl}. Run 'anvil login ${anvilUrl}' and retry.`);
50131
48881
  }
50132
48882
  }
50133
- async function resolveCheckoutUsername(anvilUrl, explicitUsername, getAccounts = auth_getAccountsForUrl) {
48883
+ function resolveCheckoutUsernameForApi(anvilUrl, explicitUsername) {
50134
48884
  if (explicitUsername) return explicitUsername;
50135
- const accounts = getAccounts(anvilUrl);
48885
+ const accounts = auth_getAccountsForUrl(anvilUrl);
50136
48886
  if (0 === accounts.length) return;
50137
- if (1 === accounts.length) {
50138
- logger_logger.verbose(chalk_source.cyan("Auto-selected account: ") + chalk_source.bold(accounts[0]));
50139
- return accounts[0];
50140
- }
50141
- const interactive = process.stdin.isTTY && process.stdout.isTTY;
50142
- if (!interactive) throw new Error(`Multiple accounts found for ${anvilUrl}. Use --user <USERNAME> to choose one.`);
50143
- const choices = accounts.map((acct)=>({
50144
- name: acct,
50145
- value: acct
50146
- }));
50147
- choices.push({
50148
- name: "Cancel",
50149
- value: null
50150
- });
50151
- return logger_logger.select(`Multiple accounts found for ${anvilUrl}. Which account should be used for checkout?`, choices, accounts[0]);
48887
+ if (1 === accounts.length) return accounts[0];
48888
+ throw new Error(`Multiple accounts found for ${anvilUrl}: ${accounts.join(", ")}. Use --user <USERNAME> to choose one.`);
50152
48889
  }
50153
48890
  async function executeCheckout(options, deps = defaultCheckoutDeps) {
50154
48891
  let checkoutInput = options.input?.trim();
50155
- let preselectedAnvilUrl;
50156
- let preselectedUsername;
50157
- if (!checkoutInput) {
50158
- if (!isInteractiveSession()) throw new Error("`anvil checkout` without arguments requires an interactive TTY. Pass APP_ID or URL explicitly in non-interactive mode.");
50159
- const selectedUrl = await resolveCheckoutUrl(options.url);
50160
- if (!selectedUrl) return void logger_logger.info("Checkout cancelled.");
50161
- preselectedAnvilUrl = selectedUrl;
50162
- const selectedUsername = await resolveCheckoutUsername(selectedUrl, options.user);
50163
- if (null === selectedUsername) return void logger_logger.info("Checkout cancelled.");
50164
- preselectedUsername = selectedUsername || void 0;
50165
- const selectedInput = await selectAppForCheckout(selectedUrl, preselectedUsername, deps, options.query);
50166
- if (!selectedInput) return void logger_logger.info("Checkout cancelled.");
50167
- checkoutInput = selectedInput;
50168
- }
48892
+ if (!checkoutInput) throw new Error("Checkout input is required. Pass an app ID, editor URL, or /git URL explicitly.");
50169
48893
  logger_logger.verbose(chalk_source.cyan("Checkout input: ") + chalk_source.bold(checkoutInput));
50170
48894
  const parsed = parseCheckoutInput(checkoutInput);
50171
48895
  logger_logger.verbose(chalk_source.cyan("Resolved app ID: ") + chalk_source.bold(parsed.appId));
50172
- const anvilUrl = preselectedAnvilUrl || await resolveCheckoutUrl(options.url, parsed.detectedUrl);
50173
- if (!anvilUrl) return void logger_logger.info("Checkout cancelled.");
50174
- const resolvedUsername = preselectedUsername || await resolveCheckoutUsername(anvilUrl, options.user);
50175
- if (null === resolvedUsername) return void logger_logger.info("Checkout cancelled.");
48896
+ const anvilUrl = resolveCheckoutUrlForApi(options.url, parsed.detectedUrl);
48897
+ if (!anvilUrl) throw new Error("Anvil URL is required. Use --url <ANVIL_URL> or pass an input URL containing the host.");
48898
+ const resolvedUsername = resolveCheckoutUsernameForApi(anvilUrl, options.user);
50176
48899
  if (resolvedUsername) logger_logger.verbose(chalk_source.cyan("Using account: ") + chalk_source.bold(resolvedUsername));
50177
48900
  else logger_logger.verbose(chalk_source.cyan("No account preselected; resolving after auth token lookup."));
50178
48901
  const authToken = await ensureCheckoutAuthToken(anvilUrl, resolvedUsername, deps);
50179
48902
  let checkoutUsername = resolvedUsername;
50180
48903
  if (!checkoutUsername) {
50181
- const inferredUsername = await resolveCheckoutUsername(anvilUrl, void 0);
50182
- if (null === inferredUsername) return void logger_logger.info("Checkout cancelled.");
48904
+ const inferredUsername = resolveCheckoutUsernameForApi(anvilUrl, void 0);
50183
48905
  if (!inferredUsername) throw new Error(`Could not determine account for ${anvilUrl}. Use --user <USERNAME> so checkout can bind repository credentials.`);
50184
48906
  checkoutUsername = inferredUsername;
50185
48907
  }
@@ -50199,8 +48921,6 @@ var __webpack_exports__ = {};
50199
48921
  if (options.branch) logger_logger.verbose(chalk_source.cyan("Requested branch: ") + chalk_source.bold(options.branch));
50200
48922
  if ("number" == typeof options.depth) logger_logger.verbose(chalk_source.cyan("Clone depth: ") + chalk_source.bold(String(options.depth)));
50201
48923
  if (options.singleBranch) logger_logger.verbose(chalk_source.cyan("Single-branch clone enabled"));
50202
- logger_logger.progress("checkout", `Checking out app ${parsed.appId} from ${anvilUrl}`);
50203
- logger_logger.info(chalk_source.gray(` Destination directory: ${destinationDisplay}`));
50204
48924
  await deps.clone(cloneUrl, destinationPath, {
50205
48925
  branch: options.branch,
50206
48926
  depth: options.depth,
@@ -50222,18 +48942,15 @@ var __webpack_exports__ = {};
50222
48942
  } catch (e) {
50223
48943
  throw new Error(`Checkout clone succeeded, but failed to configure repository credentials: ${errors_getErrorMessage(e)}. The repository exists at ${destinationDisplay}, but Git auth bridge setup is incomplete.`);
50224
48944
  }
50225
- logger_logger.progressEnd("checkout", `Checked out ${parsed.appId} into ${destinationDisplay}`);
50226
- const preferredEditor = String(config_getConfig("preferredEditor") || "").trim();
50227
- const preferredEditorCommand = preferredEditor ? config_getPreferredEditorCommand(preferredEditor) : "";
50228
- if (options.open) {
50229
- await checkout_openPathInEditorOrDefault(destinationPath, preferredEditorCommand);
50230
- logger_logger.info(chalk_source.gray(`Opened ${destinationDisplay}`));
50231
- }
50232
- if (preferredEditorCommand && !options.open) if (isCommandAvailable(preferredEditorCommand)) logger_logger.info(chalk_source.cyan(`Next: ${preferredEditorCommand} ${destinationDisplay}`));
50233
- else logger_logger.warn(`Preferred editor command '${preferredEditorCommand}' was not found in PATH. Run 'anvil configure' to choose an installed editor.`);
50234
- }
50235
- async function checkout_openPathInEditorOrDefault(destinationPath, preferredEditorCommand, deps) {
50236
- await path_open_openPathInEditorOrDefault(destinationPath, preferredEditorCommand, deps);
48945
+ return {
48946
+ appId: parsed.appId,
48947
+ appName: validation.app_name,
48948
+ anvilUrl,
48949
+ destinationPath,
48950
+ destinationDisplay,
48951
+ username: checkoutUsername,
48952
+ remoteName
48953
+ };
50237
48954
  }
50238
48955
  const api_DEFAULT_ANVIL_URL = resolveAnvilUrl();
50239
48956
  async function api_checkUncommittedChanges(repoPath) {
@@ -50256,7 +48973,8 @@ var __webpack_exports__ = {};
50256
48973
  throw errors_createGitError.commandFailed("status", e.message);
50257
48974
  }
50258
48975
  }
50259
- async function src_api_syncToLatest(repoPath, appId, anvilUrl, authToken, currentBranch, username) {
48976
+ async function src_api_syncToLatest(repoPath, appId, options) {
48977
+ const { anvilUrl, authToken, currentBranch, username } = options;
50260
48978
  try {
50261
48979
  const git = esm_default(repoPath);
50262
48980
  const commitId = (await git.revparse([
@@ -50280,7 +48998,8 @@ var __webpack_exports__ = {};
50280
48998
  throw errors_createGitError.commandFailed("sync", e instanceof Error ? e.message : String(e));
50281
48999
  }
50282
49000
  }
50283
- async function src_api_watch(repoPath, appId, anvilUrl = api_DEFAULT_ANVIL_URL, stagedOnly = false, username) {
49001
+ async function src_api_watch(repoPath, appId, options = {}) {
49002
+ const { anvilUrl = api_DEFAULT_ANVIL_URL, stagedOnly = false, username } = options;
50284
49003
  repoPath = external_path_default().resolve(repoPath);
50285
49004
  const authToken = await auth_getValidAuthToken(anvilUrl, username);
50286
49005
  await auth_verifyAuth(authToken, anvilUrl);
@@ -50307,7 +49026,11 @@ var __webpack_exports__ = {};
50307
49026
  }
50308
49027
  logger_logger.verbose(chalk_source.cyan("Current branch: ") + chalk_source.bold(currentBranch));
50309
49028
  logger_logger.verbose(chalk_source.cyan("Current commit ID: ") + chalk_source.gray(commitId));
50310
- const syncStatus = await validation_validateBranchSyncStatus(git, currentBranch, appId, anvilUrl, username);
49029
+ const syncStatus = await validation_validateBranchSyncStatus(git, currentBranch, {
49030
+ appId,
49031
+ anvilUrl,
49032
+ username
49033
+ });
50311
49034
  let hasUncommittedChanges = false;
50312
49035
  try {
50313
49036
  const status = await git.status();
@@ -50352,6 +49075,7 @@ var __webpack_exports__ = {};
50352
49075
  return session;
50353
49076
  }
50354
49077
  })();
49078
+ exports.ANVIL_SYNC_CLIENT_ID = __webpack_exports__.ANVIL_SYNC_CLIENT_ID;
50355
49079
  exports.AnvilYamlValidationResult = __webpack_exports__.AnvilYamlValidationResult;
50356
49080
  exports.AppIdCandidate = __webpack_exports__.AppIdCandidate;
50357
49081
  exports.AppIdWithContext = __webpack_exports__.AppIdWithContext;
@@ -50360,6 +49084,7 @@ exports.CheckoutAppListItem = __webpack_exports__.CheckoutAppListItem;
50360
49084
  exports.CheckoutCloneOptions = __webpack_exports__.CheckoutCloneOptions;
50361
49085
  exports.CheckoutExecutionDeps = __webpack_exports__.CheckoutExecutionDeps;
50362
49086
  exports.CheckoutOptions = __webpack_exports__.CheckoutOptions;
49087
+ exports.CheckoutResult = __webpack_exports__.CheckoutResult;
50363
49088
  exports.DeviceAuthorizationResponse = __webpack_exports__.DeviceAuthorizationResponse;
50364
49089
  exports.FormTemplateValidationResult = __webpack_exports__.FormTemplateValidationResult;
50365
49090
  exports.LoginResult = __webpack_exports__.LoginResult;
@@ -50371,14 +49096,15 @@ exports.SettableConfigKey = __webpack_exports__.SettableConfigKey;
50371
49096
  exports.StoredTokens = __webpack_exports__.StoredTokens;
50372
49097
  exports.TokenData = __webpack_exports__.TokenData;
50373
49098
  exports.ValidateAppIdResponse = __webpack_exports__.ValidateAppIdResponse;
49099
+ exports.ValidateBranchSyncStatusOptions = __webpack_exports__.ValidateBranchSyncStatusOptions;
50374
49100
  exports.ValidatePathResult = __webpack_exports__.ValidatePathResult;
50375
49101
  exports.ValidationIssue = __webpack_exports__.ValidationIssue;
50376
49102
  exports.ValidationTarget = __webpack_exports__.ValidationTarget;
49103
+ exports.WatchSession = __webpack_exports__.WatchSession;
50377
49104
  exports.checkUncommittedChanges = __webpack_exports__.checkUncommittedChanges;
50378
49105
  exports.deleteConfig = __webpack_exports__.deleteConfig;
50379
49106
  exports.detectAppIdsByCommitLookup = __webpack_exports__.detectAppIdsByCommitLookup;
50380
49107
  exports.detectAppIdsFromAllRemotes = __webpack_exports__.detectAppIdsFromAllRemotes;
50381
- exports.ensureCheckoutAuthToken = __webpack_exports__.ensureCheckoutAuthToken;
50382
49108
  exports.executeCheckout = __webpack_exports__.executeCheckout;
50383
49109
  exports.filterCandidates = __webpack_exports__.filterCandidates;
50384
49110
  exports.formatCandidateLabel = __webpack_exports__.formatCandidateLabel;
@@ -50407,7 +49133,6 @@ exports.logout = __webpack_exports__.logout;
50407
49133
  exports.lookupByCommit = __webpack_exports__.lookupByCommit;
50408
49134
  exports.lookupRemoteInfoForAppId = __webpack_exports__.lookupRemoteInfoForAppId;
50409
49135
  exports.normalizeAnvilUrl = __webpack_exports__.normalizeAnvilUrl;
50410
- exports.openPathInEditorOrDefault = __webpack_exports__.openPathInEditorOrDefault;
50411
49136
  exports.parseCheckoutInput = __webpack_exports__.parseCheckoutInput;
50412
49137
  exports.parseConfigSetValue = __webpack_exports__.parseConfigSetValue;
50413
49138
  exports.pollDeviceAuthorization = __webpack_exports__.pollDeviceAuthorization;
@@ -50415,9 +49140,6 @@ exports.preferredEditors = __webpack_exports__.preferredEditors;
50415
49140
  exports.requestDeviceAuthorization = __webpack_exports__.requestDeviceAuthorization;
50416
49141
  exports.resetConfig = __webpack_exports__.resetConfig;
50417
49142
  exports.resolveAnvilUrl = __webpack_exports__.resolveAnvilUrl;
50418
- exports.resolveCheckoutUrl = __webpack_exports__.resolveCheckoutUrl;
50419
- exports.resolveCheckoutUsername = __webpack_exports__.resolveCheckoutUsername;
50420
- exports.runInteractiveLoginFlow = __webpack_exports__.runInteractiveLoginFlow;
50421
49143
  exports.sanitizeDirectoryName = __webpack_exports__.sanitizeDirectoryName;
50422
49144
  exports.saveUpdates = __webpack_exports__.saveUpdates;
50423
49145
  exports.setAuthTokensForAccount = __webpack_exports__.setAuthTokensForAccount;
@@ -50433,6 +49155,7 @@ exports.validatePath = __webpack_exports__.validatePath;
50433
49155
  exports.verifyAuth = __webpack_exports__.verifyAuth;
50434
49156
  exports.watch = __webpack_exports__.watch;
50435
49157
  for(var __rspack_i in __webpack_exports__)if (-1 === [
49158
+ "ANVIL_SYNC_CLIENT_ID",
50436
49159
  "AnvilYamlValidationResult",
50437
49160
  "AppIdCandidate",
50438
49161
  "AppIdWithContext",
@@ -50441,6 +49164,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
50441
49164
  "CheckoutCloneOptions",
50442
49165
  "CheckoutExecutionDeps",
50443
49166
  "CheckoutOptions",
49167
+ "CheckoutResult",
50444
49168
  "DeviceAuthorizationResponse",
50445
49169
  "FormTemplateValidationResult",
50446
49170
  "LoginResult",
@@ -50452,14 +49176,15 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
50452
49176
  "StoredTokens",
50453
49177
  "TokenData",
50454
49178
  "ValidateAppIdResponse",
49179
+ "ValidateBranchSyncStatusOptions",
50455
49180
  "ValidatePathResult",
50456
49181
  "ValidationIssue",
50457
49182
  "ValidationTarget",
49183
+ "WatchSession",
50458
49184
  "checkUncommittedChanges",
50459
49185
  "deleteConfig",
50460
49186
  "detectAppIdsByCommitLookup",
50461
49187
  "detectAppIdsFromAllRemotes",
50462
- "ensureCheckoutAuthToken",
50463
49188
  "executeCheckout",
50464
49189
  "filterCandidates",
50465
49190
  "formatCandidateLabel",
@@ -50488,7 +49213,6 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
50488
49213
  "lookupByCommit",
50489
49214
  "lookupRemoteInfoForAppId",
50490
49215
  "normalizeAnvilUrl",
50491
- "openPathInEditorOrDefault",
50492
49216
  "parseCheckoutInput",
50493
49217
  "parseConfigSetValue",
50494
49218
  "pollDeviceAuthorization",
@@ -50496,9 +49220,6 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
50496
49220
  "requestDeviceAuthorization",
50497
49221
  "resetConfig",
50498
49222
  "resolveAnvilUrl",
50499
- "resolveCheckoutUrl",
50500
- "resolveCheckoutUsername",
50501
- "runInteractiveLoginFlow",
50502
49223
  "sanitizeDirectoryName",
50503
49224
  "saveUpdates",
50504
49225
  "setAuthTokensForAccount",