@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/CLILogger.d.ts +4 -4
- package/dist/CLILogger.d.ts.map +1 -1
- package/dist/SavePathRouter.d.ts +11 -1
- package/dist/SavePathRouter.d.ts.map +1 -1
- package/dist/WatchSession.d.ts +1 -0
- package/dist/WatchSession.d.ts.map +1 -1
- package/dist/api.d.ts +19 -6
- package/dist/api.d.ts.map +1 -1
- package/dist/cli.js +328 -130
- package/dist/commands/checkout.d.ts +10 -11
- package/dist/commands/checkout.d.ts.map +1 -1
- package/dist/commands/configure.d.ts.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/globalConfig.d.ts +6 -0
- package/dist/globalConfig.d.ts.map +1 -1
- package/dist/index.js +265 -1544
- package/dist/logger.d.ts +7 -3
- package/dist/logger.d.ts.map +1 -1
- package/dist/services/auth.d.ts +2 -1
- package/dist/services/auth.d.ts.map +1 -1
- package/dist/services/oauth-login.d.ts.map +1 -1
- package/dist/services/token-store.d.ts +2 -0
- package/dist/services/token-store.d.ts.map +1 -1
- package/dist/services/validation.d.ts +6 -1
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/watch/SaveProcessor.d.ts.map +1 -1
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -42250,12 +42250,13 @@ var __webpack_exports__ = {};
|
|
|
42250
42250
|
const EMPTY_TOKENS = {
|
|
42251
42251
|
authToken: null,
|
|
42252
42252
|
refreshToken: null,
|
|
42253
|
-
authTokenExpiresAt: null
|
|
42253
|
+
authTokenExpiresAt: null,
|
|
42254
|
+
clientId: null
|
|
42254
42255
|
};
|
|
42255
42256
|
function isAccountTokens(value) {
|
|
42256
42257
|
if (!value || "object" != typeof value || Array.isArray(value)) return false;
|
|
42257
42258
|
const obj = value;
|
|
42258
|
-
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);
|
|
42259
|
+
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);
|
|
42259
42260
|
}
|
|
42260
42261
|
function isUrlTokens(value) {
|
|
42261
42262
|
if (!value || "object" != typeof value || Array.isArray(value)) return false;
|
|
@@ -42319,7 +42320,8 @@ var __webpack_exports__ = {};
|
|
|
42319
42320
|
if (keychainOk) store[normalized][username] = {
|
|
42320
42321
|
authToken: null,
|
|
42321
42322
|
refreshToken: null,
|
|
42322
|
-
authTokenExpiresAt: tokens.authTokenExpiresAt
|
|
42323
|
+
authTokenExpiresAt: tokens.authTokenExpiresAt,
|
|
42324
|
+
clientId: tokens.clientId ?? null
|
|
42323
42325
|
};
|
|
42324
42326
|
else store[normalized][username] = tokens;
|
|
42325
42327
|
setTokenStore(store);
|
|
@@ -42600,6 +42602,10 @@ var __webpack_exports__ = {};
|
|
|
42600
42602
|
function getGlobalOutputConfig() {
|
|
42601
42603
|
return globalOutputConfig;
|
|
42602
42604
|
}
|
|
42605
|
+
function assertCanPrompt(action = "This command", explicitAlternative = "Pass explicit flags instead.") {
|
|
42606
|
+
if (globalOutputConfig.jsonMode) throw new Error(`${action} requires interactive input, but --json disables prompts. ${explicitAlternative}`);
|
|
42607
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error(`${action} requires interactive input, but stdin/stdout is not a TTY. ${explicitAlternative}`);
|
|
42608
|
+
}
|
|
42603
42609
|
const logger_timestamp = ()=>new Date().toISOString();
|
|
42604
42610
|
const verboseTimestamp = ()=>{
|
|
42605
42611
|
const now = new Date();
|
|
@@ -42706,14 +42712,32 @@ var __webpack_exports__ = {};
|
|
|
42706
42712
|
resume() {
|
|
42707
42713
|
this.paused = false;
|
|
42708
42714
|
}
|
|
42709
|
-
async prompt(questions) {
|
|
42715
|
+
async prompt(questions, options) {
|
|
42716
|
+
assertCanPrompt(options?.action ?? "Prompt", options?.nonInteractiveHint);
|
|
42710
42717
|
throw new Error("Prompting not supported in DefaultLogger. Use CLILogger for interactive prompts.");
|
|
42711
42718
|
}
|
|
42712
|
-
async confirm(message, defaultValue = true) {
|
|
42713
|
-
|
|
42719
|
+
async confirm(message, defaultValue = true, options) {
|
|
42720
|
+
const answer = await this.prompt([
|
|
42721
|
+
{
|
|
42722
|
+
type: "confirm",
|
|
42723
|
+
name: "value",
|
|
42724
|
+
message,
|
|
42725
|
+
default: defaultValue
|
|
42726
|
+
}
|
|
42727
|
+
], options);
|
|
42728
|
+
return answer.value;
|
|
42714
42729
|
}
|
|
42715
|
-
async select(message, choices, defaultValue) {
|
|
42716
|
-
|
|
42730
|
+
async select(message, choices, defaultValue, options) {
|
|
42731
|
+
const answer = await this.prompt([
|
|
42732
|
+
{
|
|
42733
|
+
type: "list",
|
|
42734
|
+
name: "value",
|
|
42735
|
+
message,
|
|
42736
|
+
choices,
|
|
42737
|
+
default: defaultValue
|
|
42738
|
+
}
|
|
42739
|
+
], options);
|
|
42740
|
+
return answer.value;
|
|
42717
42741
|
}
|
|
42718
42742
|
}
|
|
42719
42743
|
let logger_logger = new DefaultLogger();
|
|
@@ -42854,7 +42878,8 @@ var __webpack_exports__ = {};
|
|
|
42854
42878
|
setVerbose(value) {
|
|
42855
42879
|
this.sessionVerbose = value;
|
|
42856
42880
|
}
|
|
42857
|
-
async prompt(questions) {
|
|
42881
|
+
async prompt(questions, options) {
|
|
42882
|
+
assertCanPrompt(options?.action ?? "Prompt", options?.nonInteractiveHint);
|
|
42858
42883
|
this.pause();
|
|
42859
42884
|
try {
|
|
42860
42885
|
return await inquirer_dist_esm.prompt(questions);
|
|
@@ -42862,7 +42887,7 @@ var __webpack_exports__ = {};
|
|
|
42862
42887
|
this.resume();
|
|
42863
42888
|
}
|
|
42864
42889
|
}
|
|
42865
|
-
async confirm(message, defaultValue = true) {
|
|
42890
|
+
async confirm(message, defaultValue = true, options) {
|
|
42866
42891
|
const answer = await this.prompt([
|
|
42867
42892
|
{
|
|
42868
42893
|
type: "confirm",
|
|
@@ -42870,10 +42895,10 @@ var __webpack_exports__ = {};
|
|
|
42870
42895
|
message,
|
|
42871
42896
|
default: defaultValue
|
|
42872
42897
|
}
|
|
42873
|
-
]);
|
|
42898
|
+
], options);
|
|
42874
42899
|
return answer.value;
|
|
42875
42900
|
}
|
|
42876
|
-
async select(message, choices, defaultValue) {
|
|
42901
|
+
async select(message, choices, defaultValue, options) {
|
|
42877
42902
|
const answer = await this.prompt([
|
|
42878
42903
|
{
|
|
42879
42904
|
type: "list",
|
|
@@ -42883,7 +42908,7 @@ var __webpack_exports__ = {};
|
|
|
42883
42908
|
default: defaultValue,
|
|
42884
42909
|
loop: false
|
|
42885
42910
|
}
|
|
42886
|
-
]);
|
|
42911
|
+
], options);
|
|
42887
42912
|
return answer.value;
|
|
42888
42913
|
}
|
|
42889
42914
|
}
|
|
@@ -47243,6 +47268,7 @@ var __webpack_exports__ = {};
|
|
|
47243
47268
|
function getDefaultAnvilUrl() {
|
|
47244
47269
|
return resolveAnvilUrl();
|
|
47245
47270
|
}
|
|
47271
|
+
const ANVIL_SYNC_CLIENT_ID = "anvil-sync";
|
|
47246
47272
|
async function verifyAuth(authToken, anvilUrl = getDefaultAnvilUrl()) {
|
|
47247
47273
|
try {
|
|
47248
47274
|
const resp = await fetch(`${anvilUrl}/ide/api/_/user`, {
|
|
@@ -47262,7 +47288,7 @@ var __webpack_exports__ = {};
|
|
|
47262
47288
|
throw errors_createAuthError.invalid(`Network error: ${e.message}`);
|
|
47263
47289
|
}
|
|
47264
47290
|
}
|
|
47265
|
-
async function refreshAccessToken(refreshToken, anvilUrl = getDefaultAnvilUrl()) {
|
|
47291
|
+
async function refreshAccessToken(refreshToken, anvilUrl = getDefaultAnvilUrl(), clientId = ANVIL_SYNC_CLIENT_ID) {
|
|
47266
47292
|
try {
|
|
47267
47293
|
const tokenResponse = await fetch(`${anvilUrl}/oauth/token`, {
|
|
47268
47294
|
method: "POST",
|
|
@@ -47272,7 +47298,7 @@ var __webpack_exports__ = {};
|
|
|
47272
47298
|
body: new URLSearchParams({
|
|
47273
47299
|
grant_type: "refresh_token",
|
|
47274
47300
|
refresh_token: refreshToken,
|
|
47275
|
-
client_id:
|
|
47301
|
+
client_id: clientId
|
|
47276
47302
|
})
|
|
47277
47303
|
});
|
|
47278
47304
|
if (!tokenResponse.ok) {
|
|
@@ -47295,7 +47321,8 @@ var __webpack_exports__ = {};
|
|
|
47295
47321
|
if (!tokens.authToken && !tokens.refreshToken) throw errors_createAuthError.required("Not logged in. Please log in first.");
|
|
47296
47322
|
const isExpired = null !== tokens.authTokenExpiresAt && tokens.authTokenExpiresAt <= Math.floor(Date.now() / 1000) + 60;
|
|
47297
47323
|
if (tokens.refreshToken && isExpired) try {
|
|
47298
|
-
const
|
|
47324
|
+
const clientId = tokens.clientId ?? ANVIL_SYNC_CLIENT_ID;
|
|
47325
|
+
const tokenData = await refreshAccessToken(tokens.refreshToken, normalized, clientId);
|
|
47299
47326
|
const newExpiresAt = Math.floor(Date.now() / 1000) + tokenData.expires_in;
|
|
47300
47327
|
let accountUsername = username;
|
|
47301
47328
|
if (!accountUsername) {
|
|
@@ -47312,7 +47339,8 @@ var __webpack_exports__ = {};
|
|
|
47312
47339
|
setAccountTokens(normalized, accountUsername, {
|
|
47313
47340
|
authToken: tokenData.access_token,
|
|
47314
47341
|
refreshToken: tokenData.refresh_token,
|
|
47315
|
-
authTokenExpiresAt: newExpiresAt
|
|
47342
|
+
authTokenExpiresAt: newExpiresAt,
|
|
47343
|
+
clientId
|
|
47316
47344
|
});
|
|
47317
47345
|
return tokenData.access_token;
|
|
47318
47346
|
} catch (e) {
|
|
@@ -47337,7 +47365,8 @@ var __webpack_exports__ = {};
|
|
|
47337
47365
|
setAccountTokens(normalized, username, {
|
|
47338
47366
|
authToken: tokenData.access_token,
|
|
47339
47367
|
refreshToken: tokenData.refresh_token,
|
|
47340
|
-
authTokenExpiresAt: expiresAt
|
|
47368
|
+
authTokenExpiresAt: expiresAt,
|
|
47369
|
+
clientId: ANVIL_SYNC_CLIENT_ID
|
|
47341
47370
|
});
|
|
47342
47371
|
return {
|
|
47343
47372
|
success: true,
|
|
@@ -48731,7 +48760,9 @@ var __webpack_exports__ = {};
|
|
|
48731
48760
|
};
|
|
48732
48761
|
return null;
|
|
48733
48762
|
}
|
|
48734
|
-
async function loadFormTemplateData(
|
|
48763
|
+
async function loadFormTemplateData(relativePath, templateInfo, context) {
|
|
48764
|
+
const { repoPath, stagedOnly = false } = context;
|
|
48765
|
+
const { kind, format } = templateInfo;
|
|
48735
48766
|
try {
|
|
48736
48767
|
const content = await readFileContent(repoPath, relativePath, stagedOnly);
|
|
48737
48768
|
if ("yaml" === format) {
|
|
@@ -48819,7 +48850,8 @@ var __webpack_exports__ = {};
|
|
|
48819
48850
|
if (formTemplateInfo) return "forms";
|
|
48820
48851
|
return null;
|
|
48821
48852
|
}
|
|
48822
|
-
async function validateRename(fromPath, toPath,
|
|
48853
|
+
async function validateRename(fromPath, toPath, context) {
|
|
48854
|
+
const { repoPath, editorYaml } = context;
|
|
48823
48855
|
const fromEntityType = await getEntityTypeFromPath(repoPath, fromPath, editorYaml);
|
|
48824
48856
|
const toEntityType = await getEntityTypeFromPath(repoPath, toPath, editorYaml);
|
|
48825
48857
|
if (null === fromEntityType || null === toEntityType) return {
|
|
@@ -48977,7 +49009,8 @@ var __webpack_exports__ = {};
|
|
|
48977
49009
|
}
|
|
48978
49010
|
return filtered;
|
|
48979
49011
|
}
|
|
48980
|
-
async function routeFileChange(
|
|
49012
|
+
async function routeFileChange(change, context) {
|
|
49013
|
+
const { relativePath, changeType, fromPath } = change;
|
|
48981
49014
|
logger_logger.verbose(chalk_source.gray(`Routing ${changeType}: ${relativePath}${fromPath ? ` (from: ${fromPath})` : ""}`));
|
|
48982
49015
|
if (isGitRelatedFile(relativePath)) return {
|
|
48983
49016
|
type: "ignore",
|
|
@@ -48990,9 +49023,12 @@ var __webpack_exports__ = {};
|
|
|
48990
49023
|
type: "ignore",
|
|
48991
49024
|
reason: "Rename operation missing from path"
|
|
48992
49025
|
};
|
|
48993
|
-
return await handleRename(
|
|
49026
|
+
return await handleRename({
|
|
49027
|
+
fromPath,
|
|
49028
|
+
toPath: relativePath
|
|
49029
|
+
}, context);
|
|
48994
49030
|
}
|
|
48995
|
-
return await routeSavableChange(
|
|
49031
|
+
return await routeSavableChange(change, context);
|
|
48996
49032
|
}
|
|
48997
49033
|
function isGitRelatedFile(relativePath) {
|
|
48998
49034
|
return ".git" === relativePath || relativePath.startsWith(".git/") || relativePath.endsWith("/.git");
|
|
@@ -49011,47 +49047,60 @@ var __webpack_exports__ = {};
|
|
|
49011
49047
|
const parts = relativePath.split("/");
|
|
49012
49048
|
return 2 === parts.length;
|
|
49013
49049
|
},
|
|
49014
|
-
handle:
|
|
49050
|
+
handle: handleScriptsChange
|
|
49015
49051
|
},
|
|
49016
49052
|
{
|
|
49017
49053
|
matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py"),
|
|
49018
|
-
handle:
|
|
49054
|
+
handle: handleServerCodeChange
|
|
49019
49055
|
},
|
|
49020
49056
|
{
|
|
49021
49057
|
matches: (relativePath)=>relativePath.startsWith("client_code/") && relativePath.endsWith(".py"),
|
|
49022
|
-
handle:
|
|
49058
|
+
handle: handleClientCodeChange
|
|
49023
49059
|
},
|
|
49024
49060
|
{
|
|
49025
49061
|
matches: (relativePath)=>null !== detectFormTemplate(relativePath),
|
|
49026
|
-
handle:
|
|
49062
|
+
handle: handleFormTemplateChange
|
|
49027
49063
|
},
|
|
49028
49064
|
{
|
|
49029
49065
|
matches: (relativePath)=>"theme/parameters.yaml" === relativePath,
|
|
49030
|
-
handle:
|
|
49066
|
+
handle: handleThemeParametersChange
|
|
49031
49067
|
},
|
|
49032
49068
|
{
|
|
49033
49069
|
matches: (relativePath)=>relativePath.startsWith("theme/assets/"),
|
|
49034
|
-
handle:
|
|
49070
|
+
handle: handleAssetChange
|
|
49035
49071
|
},
|
|
49036
49072
|
{
|
|
49037
49073
|
matches: ()=>true,
|
|
49038
|
-
handle:
|
|
49074
|
+
handle: handleExtraFileChange
|
|
49039
49075
|
}
|
|
49040
49076
|
];
|
|
49041
|
-
async function handleRename(
|
|
49042
|
-
const
|
|
49077
|
+
async function handleRename(rename, context) {
|
|
49078
|
+
const { fromPath, toPath } = rename;
|
|
49079
|
+
const validation = await validateRename(fromPath, toPath, context);
|
|
49043
49080
|
if (!validation.valid) {
|
|
49044
49081
|
logger_logger.verbose(chalk_source.yellow(`Rename invalid (${validation.reason}), falling back to unlink + add`));
|
|
49045
|
-
const unlinkResult = await routeFileChange(
|
|
49046
|
-
|
|
49082
|
+
const unlinkResult = await routeFileChange({
|
|
49083
|
+
relativePath: fromPath,
|
|
49084
|
+
changeType: "unlink"
|
|
49085
|
+
}, context);
|
|
49086
|
+
const addResult = await routeFileChange({
|
|
49087
|
+
relativePath: toPath,
|
|
49088
|
+
changeType: "add"
|
|
49089
|
+
}, context);
|
|
49047
49090
|
return [
|
|
49048
49091
|
unlinkResult,
|
|
49049
49092
|
addResult
|
|
49050
49093
|
].flat();
|
|
49051
49094
|
}
|
|
49052
|
-
return await handleRenameOperation(
|
|
49095
|
+
return await handleRenameOperation({
|
|
49096
|
+
fromPath,
|
|
49097
|
+
toPath,
|
|
49098
|
+
entityType: validation.entityType
|
|
49099
|
+
}, context);
|
|
49053
49100
|
}
|
|
49054
|
-
async function handleRenameOperation(
|
|
49101
|
+
async function handleRenameOperation(rename, context) {
|
|
49102
|
+
const { repoPath, editorYaml, stagedOnly = false } = context;
|
|
49103
|
+
const { fromPath, toPath, entityType } = rename;
|
|
49055
49104
|
let oldName;
|
|
49056
49105
|
let newName;
|
|
49057
49106
|
let prefix = [];
|
|
@@ -49060,10 +49109,10 @@ var __webpack_exports__ = {};
|
|
|
49060
49109
|
let isPackage = false;
|
|
49061
49110
|
let actualToPath = toPath;
|
|
49062
49111
|
if ("scripts" === entityType) {
|
|
49063
|
-
const toRenameResult = await handlePathRenaming(
|
|
49112
|
+
const toRenameResult = await handlePathRenaming(toPath, "scripts", context);
|
|
49064
49113
|
if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
|
|
49065
49114
|
actualToPath = toRenameResult.newRelativePath;
|
|
49066
|
-
const fromRenameResult = await handlePathRenaming(
|
|
49115
|
+
const fromRenameResult = await handlePathRenaming(fromPath, "scripts", context);
|
|
49067
49116
|
oldName = fromRenameResult.pythonifiedName;
|
|
49068
49117
|
newName = toRenameResult.pythonifiedName;
|
|
49069
49118
|
prefix = [
|
|
@@ -49075,10 +49124,10 @@ var __webpack_exports__ = {};
|
|
|
49075
49124
|
code
|
|
49076
49125
|
});
|
|
49077
49126
|
} else if ("server_modules" === entityType) {
|
|
49078
|
-
const toRenameResult = await handlePathRenaming(
|
|
49127
|
+
const toRenameResult = await handlePathRenaming(toPath, "server_code", context);
|
|
49079
49128
|
if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
|
|
49080
49129
|
actualToPath = toRenameResult.newRelativePath;
|
|
49081
|
-
const fromRenameResult = await handlePathRenaming(
|
|
49130
|
+
const fromRenameResult = await handlePathRenaming(fromPath, "server_code", context);
|
|
49082
49131
|
oldName = fromRenameResult.pythonifiedName;
|
|
49083
49132
|
newName = toRenameResult.pythonifiedName;
|
|
49084
49133
|
prefix = [
|
|
@@ -49092,10 +49141,10 @@ var __webpack_exports__ = {};
|
|
|
49092
49141
|
is_package: isPackage
|
|
49093
49142
|
});
|
|
49094
49143
|
} else if ("modules" === entityType) {
|
|
49095
|
-
const toRenameResult = await handlePathRenaming(
|
|
49144
|
+
const toRenameResult = await handlePathRenaming(toPath, "client_code", context);
|
|
49096
49145
|
if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
|
|
49097
49146
|
actualToPath = toRenameResult.newRelativePath;
|
|
49098
|
-
const fromRenameResult = await handlePathRenaming(
|
|
49147
|
+
const fromRenameResult = await handlePathRenaming(fromPath, "client_code", context);
|
|
49099
49148
|
oldName = fromRenameResult.pythonifiedName;
|
|
49100
49149
|
newName = toRenameResult.pythonifiedName;
|
|
49101
49150
|
isPackage = actualToPath.endsWith("__init__.py");
|
|
@@ -49113,10 +49162,10 @@ var __webpack_exports__ = {};
|
|
|
49113
49162
|
type: "ignore",
|
|
49114
49163
|
reason: "Form template rename to .yaml file is only supported when entire form is renamed"
|
|
49115
49164
|
};
|
|
49116
|
-
const toRenameResult = await handlePathRenaming(
|
|
49165
|
+
const toRenameResult = await handlePathRenaming(toPath, "client_code", context);
|
|
49117
49166
|
if (toRenameResult.ignoreResult) return toRenameResult.ignoreResult;
|
|
49118
49167
|
actualToPath = toRenameResult.newRelativePath;
|
|
49119
|
-
const fromRenameResult = await handlePathRenaming(
|
|
49168
|
+
const fromRenameResult = await handlePathRenaming(fromPath, "client_code", context);
|
|
49120
49169
|
oldName = fromRenameResult.pythonifiedName;
|
|
49121
49170
|
const isPackageInit = actualToPath.endsWith("__init__.py");
|
|
49122
49171
|
const kind = isPackageInit ? "package" : "module";
|
|
@@ -49125,7 +49174,10 @@ var __webpack_exports__ = {};
|
|
|
49125
49174
|
type: "ignore",
|
|
49126
49175
|
reason: "Form template not found for rename destination"
|
|
49127
49176
|
};
|
|
49128
|
-
const result = await buildFormTemplateData(
|
|
49177
|
+
const result = await buildFormTemplateData(templateInfo.relativePath, {
|
|
49178
|
+
kind,
|
|
49179
|
+
format: templateInfo.format
|
|
49180
|
+
}, context);
|
|
49129
49181
|
if (result.ignoreResult) return result.ignoreResult;
|
|
49130
49182
|
newName = result.className;
|
|
49131
49183
|
prefix = [
|
|
@@ -49173,7 +49225,9 @@ var __webpack_exports__ = {};
|
|
|
49173
49225
|
content: payload
|
|
49174
49226
|
};
|
|
49175
49227
|
}
|
|
49176
|
-
async function routeSavableChange(
|
|
49228
|
+
async function routeSavableChange(change, context) {
|
|
49229
|
+
const { repoPath, editorYaml, stagedOnly = false } = context;
|
|
49230
|
+
const { relativePath, changeType } = change;
|
|
49177
49231
|
if ("anvil.yaml" === relativePath) return {
|
|
49178
49232
|
type: "ignore",
|
|
49179
49233
|
reason: "anvil.yaml handled specially (multiple save paths)"
|
|
@@ -49217,13 +49271,15 @@ var __webpack_exports__ = {};
|
|
|
49217
49271
|
};
|
|
49218
49272
|
}
|
|
49219
49273
|
if ("unlink" === changeType) return await handleFileDeletion(repoPath, relativePath, editorYaml);
|
|
49220
|
-
for (const route of ROUTES)if (route.matches(relativePath)) return await route.handle(
|
|
49274
|
+
for (const route of ROUTES)if (route.matches(relativePath)) return await route.handle(change, context);
|
|
49221
49275
|
return {
|
|
49222
49276
|
type: "ignore",
|
|
49223
49277
|
reason: "Not a recognized Anvil file type"
|
|
49224
49278
|
};
|
|
49225
49279
|
}
|
|
49226
|
-
async function handleThemeParametersChange(
|
|
49280
|
+
async function handleThemeParametersChange(change, context) {
|
|
49281
|
+
const { repoPath, stagedOnly = false } = context;
|
|
49282
|
+
const { relativePath } = change;
|
|
49227
49283
|
const content = await readFileContent(repoPath, relativePath, stagedOnly);
|
|
49228
49284
|
const parametersData = jsYaml.load(content);
|
|
49229
49285
|
return {
|
|
@@ -49235,7 +49291,9 @@ var __webpack_exports__ = {};
|
|
|
49235
49291
|
content: parametersData
|
|
49236
49292
|
};
|
|
49237
49293
|
}
|
|
49238
|
-
async function handleExtraFileChange(
|
|
49294
|
+
async function handleExtraFileChange(change, context) {
|
|
49295
|
+
const { repoPath, stagedOnly = false } = context;
|
|
49296
|
+
const { relativePath } = change;
|
|
49239
49297
|
const content = await readBinaryFileContent(repoPath, relativePath, stagedOnly);
|
|
49240
49298
|
const base64Content = content.toString("base64");
|
|
49241
49299
|
const pathParts = [
|
|
@@ -49248,7 +49306,9 @@ var __webpack_exports__ = {};
|
|
|
49248
49306
|
content: base64Content
|
|
49249
49307
|
};
|
|
49250
49308
|
}
|
|
49251
|
-
async function handleDirectoryRenaming(
|
|
49309
|
+
async function handleDirectoryRenaming(rename, context) {
|
|
49310
|
+
const { repoPath } = context;
|
|
49311
|
+
const { originalParts, pythonifiedParts, baseDir } = rename;
|
|
49252
49312
|
const needsRename = originalParts.some((part, idx)=>part !== pythonifiedParts[idx]);
|
|
49253
49313
|
if (!needsRename) return null;
|
|
49254
49314
|
const needsDirRename = originalParts.slice(0, -1).some((part, idx)=>part !== pythonifiedParts[idx]);
|
|
@@ -49266,7 +49326,9 @@ var __webpack_exports__ = {};
|
|
|
49266
49326
|
}
|
|
49267
49327
|
return null;
|
|
49268
49328
|
}
|
|
49269
|
-
async function renameIfNeeded(
|
|
49329
|
+
async function renameIfNeeded(rename, context) {
|
|
49330
|
+
const { repoPath } = context;
|
|
49331
|
+
const { relativePath, originalNameOrParts, baseDir } = rename;
|
|
49270
49332
|
let pythonifiedName;
|
|
49271
49333
|
let pythonifiedParts;
|
|
49272
49334
|
let needsRename;
|
|
@@ -49304,8 +49366,10 @@ var __webpack_exports__ = {};
|
|
|
49304
49366
|
ignoreResult
|
|
49305
49367
|
};
|
|
49306
49368
|
}
|
|
49307
|
-
async function handleScriptsChange(
|
|
49308
|
-
const
|
|
49369
|
+
async function handleScriptsChange(change, context) {
|
|
49370
|
+
const { repoPath, editorYaml, stagedOnly = false } = context;
|
|
49371
|
+
const { relativePath, changeType } = change;
|
|
49372
|
+
const renameResult = await handlePathRenaming(relativePath, "scripts", context);
|
|
49309
49373
|
if (renameResult.ignoreResult) return renameResult.ignoreResult;
|
|
49310
49374
|
const actualPath = renameResult.newRelativePath;
|
|
49311
49375
|
const content = await readFileContent(repoPath, actualPath, stagedOnly);
|
|
@@ -49327,8 +49391,10 @@ var __webpack_exports__ = {};
|
|
|
49327
49391
|
]
|
|
49328
49392
|
});
|
|
49329
49393
|
}
|
|
49330
|
-
async function handleServerCodeChange(
|
|
49331
|
-
const
|
|
49394
|
+
async function handleServerCodeChange(change, context) {
|
|
49395
|
+
const { repoPath, editorYaml, stagedOnly = false } = context;
|
|
49396
|
+
const { relativePath, changeType } = change;
|
|
49397
|
+
const renameResult = await handlePathRenaming(relativePath, "server_code", context);
|
|
49332
49398
|
if (renameResult.ignoreResult) return renameResult.ignoreResult;
|
|
49333
49399
|
const actualPath = renameResult.newRelativePath;
|
|
49334
49400
|
const isPackage = actualPath.endsWith("__init__.py");
|
|
@@ -49353,8 +49419,10 @@ var __webpack_exports__ = {};
|
|
|
49353
49419
|
]
|
|
49354
49420
|
});
|
|
49355
49421
|
}
|
|
49356
|
-
async function handleClientCodeFormChange(
|
|
49357
|
-
const
|
|
49422
|
+
async function handleClientCodeFormChange(options, context) {
|
|
49423
|
+
const { editorYaml } = context;
|
|
49424
|
+
const { templatePath, templateInfo, changeType } = options;
|
|
49425
|
+
const result = await buildFormTemplateData(templatePath, templateInfo, context);
|
|
49358
49426
|
if (result.ignoreResult) return result.ignoreResult;
|
|
49359
49427
|
const { formData, className: extractedClassName } = result;
|
|
49360
49428
|
return handleIdBasedOperation({
|
|
@@ -49372,30 +49440,47 @@ var __webpack_exports__ = {};
|
|
|
49372
49440
|
]
|
|
49373
49441
|
});
|
|
49374
49442
|
}
|
|
49375
|
-
async function handlePathRenaming(
|
|
49443
|
+
async function handlePathRenaming(relativePath, baseDir, context) {
|
|
49376
49444
|
const parts = relativePath.slice(0, -3).split("/");
|
|
49377
49445
|
const originalParts = parts.slice(1);
|
|
49378
49446
|
const pythonifiedParts = originalParts.map(pythonifyName);
|
|
49379
49447
|
const pythonifiedName = extractPythonName(relativePath);
|
|
49380
|
-
const dirRenameResult = await handleDirectoryRenaming(
|
|
49448
|
+
const dirRenameResult = await handleDirectoryRenaming({
|
|
49449
|
+
originalParts,
|
|
49450
|
+
pythonifiedParts,
|
|
49451
|
+
baseDir
|
|
49452
|
+
}, context);
|
|
49381
49453
|
if (dirRenameResult) return {
|
|
49382
49454
|
pythonifiedName,
|
|
49383
49455
|
pythonifiedParts,
|
|
49384
49456
|
newRelativePath: relativePath,
|
|
49385
49457
|
ignoreResult: dirRenameResult
|
|
49386
49458
|
};
|
|
49387
|
-
const renameResult = await renameIfNeeded(
|
|
49459
|
+
const renameResult = await renameIfNeeded({
|
|
49460
|
+
relativePath,
|
|
49461
|
+
originalNameOrParts: originalParts,
|
|
49462
|
+
baseDir
|
|
49463
|
+
}, context);
|
|
49388
49464
|
return renameResult;
|
|
49389
49465
|
}
|
|
49390
|
-
async function handleClientCodeChange(
|
|
49391
|
-
const
|
|
49466
|
+
async function handleClientCodeChange(change, context) {
|
|
49467
|
+
const { repoPath, editorYaml, stagedOnly = false } = context;
|
|
49468
|
+
const { relativePath, changeType } = change;
|
|
49469
|
+
const renameResult = await handlePathRenaming(relativePath, "client_code", context);
|
|
49392
49470
|
if (renameResult.ignoreResult) return renameResult.ignoreResult;
|
|
49393
49471
|
const actualPath = renameResult.newRelativePath;
|
|
49394
49472
|
const isPackageInit = actualPath.endsWith("__init__.py");
|
|
49395
49473
|
const kind = isPackageInit ? "package" : "module";
|
|
49396
49474
|
const className = renameResult.pythonifiedName;
|
|
49397
49475
|
const templateInfo = findFormTemplateForCodePath(repoPath, actualPath, kind);
|
|
49398
|
-
if (templateInfo) return await handleClientCodeFormChange(
|
|
49476
|
+
if (templateInfo) return await handleClientCodeFormChange({
|
|
49477
|
+
templatePath: templateInfo.relativePath,
|
|
49478
|
+
templateInfo: {
|
|
49479
|
+
format: templateInfo.format,
|
|
49480
|
+
kind
|
|
49481
|
+
},
|
|
49482
|
+
changeType
|
|
49483
|
+
}, context);
|
|
49399
49484
|
const content = await readFileContent(repoPath, actualPath, stagedOnly);
|
|
49400
49485
|
return handleIdBasedOperation({
|
|
49401
49486
|
entityType: "modules",
|
|
@@ -49430,8 +49515,10 @@ var __webpack_exports__ = {};
|
|
|
49430
49515
|
}
|
|
49431
49516
|
return formData;
|
|
49432
49517
|
}
|
|
49433
|
-
async function buildFormTemplateData(
|
|
49434
|
-
const
|
|
49518
|
+
async function buildFormTemplateData(relativePath, templateInfo, context) {
|
|
49519
|
+
const { repoPath, stagedOnly = false } = context;
|
|
49520
|
+
const { kind } = templateInfo;
|
|
49521
|
+
const loadResult = await loadFormTemplateData(relativePath, templateInfo, context);
|
|
49435
49522
|
if (false === loadResult.ok) return {
|
|
49436
49523
|
formData: {},
|
|
49437
49524
|
className: "",
|
|
@@ -49465,7 +49552,9 @@ var __webpack_exports__ = {};
|
|
|
49465
49552
|
ignoreResult: null
|
|
49466
49553
|
};
|
|
49467
49554
|
}
|
|
49468
|
-
async function handleFormTemplateChange(
|
|
49555
|
+
async function handleFormTemplateChange(change, context) {
|
|
49556
|
+
const { editorYaml } = context;
|
|
49557
|
+
const { relativePath, changeType } = change;
|
|
49469
49558
|
const templateInfo = detectFormTemplate(relativePath);
|
|
49470
49559
|
if (!templateInfo) return {
|
|
49471
49560
|
type: "ignore",
|
|
@@ -49473,7 +49562,10 @@ var __webpack_exports__ = {};
|
|
|
49473
49562
|
};
|
|
49474
49563
|
const kind = templateInfo.kind;
|
|
49475
49564
|
const format = templateInfo.format;
|
|
49476
|
-
const result = await buildFormTemplateData(
|
|
49565
|
+
const result = await buildFormTemplateData(relativePath, {
|
|
49566
|
+
kind,
|
|
49567
|
+
format
|
|
49568
|
+
}, context);
|
|
49477
49569
|
if (result.ignoreResult) return result.ignoreResult;
|
|
49478
49570
|
const { formData, className } = result;
|
|
49479
49571
|
return handleIdBasedOperation({
|
|
@@ -49489,7 +49581,9 @@ var __webpack_exports__ = {};
|
|
|
49489
49581
|
subPathForCodeUpdate: null
|
|
49490
49582
|
});
|
|
49491
49583
|
}
|
|
49492
|
-
async function handleAssetChange(
|
|
49584
|
+
async function handleAssetChange(change, context) {
|
|
49585
|
+
const { repoPath, editorYaml, stagedOnly = false } = context;
|
|
49586
|
+
const { relativePath, changeType } = change;
|
|
49493
49587
|
const assetPath = relativePath.replace(/^theme[\/\\]assets[\/\\]/, "");
|
|
49494
49588
|
const fileBuffer = await readBinaryFileContent(repoPath, relativePath, stagedOnly);
|
|
49495
49589
|
const base64Content = fileBuffer.toString("base64");
|
|
@@ -49916,7 +50010,15 @@ var __webpack_exports__ = {};
|
|
|
49916
50010
|
originalFilePaths.push(change.path);
|
|
49917
50011
|
continue;
|
|
49918
50012
|
}
|
|
49919
|
-
const routeResult = await routeFileChange(
|
|
50013
|
+
const routeResult = await routeFileChange({
|
|
50014
|
+
relativePath: change.path,
|
|
50015
|
+
changeType: change.type,
|
|
50016
|
+
fromPath: change.from
|
|
50017
|
+
}, {
|
|
50018
|
+
repoPath: this.config.repoPath,
|
|
50019
|
+
editorYaml: this.config.editorYaml,
|
|
50020
|
+
stagedOnly: this.config.stagedOnly
|
|
50021
|
+
});
|
|
49920
50022
|
const results = Array.isArray(routeResult) ? routeResult : [
|
|
49921
50023
|
routeResult
|
|
49922
50024
|
];
|
|
@@ -50103,7 +50205,15 @@ var __webpack_exports__ = {};
|
|
|
50103
50205
|
const newSaveArray = [];
|
|
50104
50206
|
const newFilePaths = [];
|
|
50105
50207
|
for (const change of changes){
|
|
50106
|
-
const routeResult = await routeFileChange(
|
|
50208
|
+
const routeResult = await routeFileChange({
|
|
50209
|
+
relativePath: change.path,
|
|
50210
|
+
changeType: change.type,
|
|
50211
|
+
fromPath: change.from
|
|
50212
|
+
}, {
|
|
50213
|
+
repoPath: this.config.repoPath,
|
|
50214
|
+
editorYaml: this.config.editorYaml,
|
|
50215
|
+
stagedOnly: this.config.stagedOnly
|
|
50216
|
+
});
|
|
50107
50217
|
const results = Array.isArray(routeResult) ? routeResult : [
|
|
50108
50218
|
routeResult
|
|
50109
50219
|
];
|
|
@@ -50501,6 +50611,12 @@ var __webpack_exports__ = {};
|
|
|
50501
50611
|
this.startLocalChangeFallbackPolling();
|
|
50502
50612
|
await new Promise(()=>{});
|
|
50503
50613
|
}
|
|
50614
|
+
startWatchingInBackground(onError) {
|
|
50615
|
+
this.startWatching().catch((error)=>{
|
|
50616
|
+
this.cleanup();
|
|
50617
|
+
onError?.(error);
|
|
50618
|
+
});
|
|
50619
|
+
}
|
|
50504
50620
|
async initializeLocalChangeFingerprint() {
|
|
50505
50621
|
if (this.stagedOnly) return;
|
|
50506
50622
|
try {
|
|
@@ -50637,22 +50753,28 @@ var __webpack_exports__ = {};
|
|
|
50637
50753
|
appName
|
|
50638
50754
|
};
|
|
50639
50755
|
}
|
|
50640
|
-
async function validateBranchSyncStatus(git, branchName,
|
|
50756
|
+
async function validateBranchSyncStatus(git, branchName, options) {
|
|
50757
|
+
const { appId, anvilUrl, username } = options;
|
|
50641
50758
|
logger_logger.verbose(chalk_source.blue("Checking branch sync status..."));
|
|
50642
50759
|
let authToken;
|
|
50643
50760
|
try {
|
|
50644
50761
|
authToken = await auth_getValidAuthToken(anvilUrl, username);
|
|
50645
50762
|
} catch (e) {
|
|
50646
|
-
return validateViaAnvilServer(git, branchName,
|
|
50763
|
+
return validateViaAnvilServer(git, branchName, options);
|
|
50647
50764
|
}
|
|
50648
50765
|
try {
|
|
50649
|
-
return await validateViaGitFetch(git, branchName,
|
|
50766
|
+
return await validateViaGitFetch(git, branchName, {
|
|
50767
|
+
appId,
|
|
50768
|
+
anvilUrl,
|
|
50769
|
+
authToken
|
|
50770
|
+
});
|
|
50650
50771
|
} catch (e) {
|
|
50651
50772
|
logger_logger.verbose(chalk_source.yellow("Git fetch failed, trying server validation..."));
|
|
50652
|
-
return validateViaAnvilServer(git, branchName,
|
|
50773
|
+
return validateViaAnvilServer(git, branchName, options);
|
|
50653
50774
|
}
|
|
50654
50775
|
}
|
|
50655
|
-
async function validateViaGitFetch(git, branchName,
|
|
50776
|
+
async function validateViaGitFetch(git, branchName, options) {
|
|
50777
|
+
const { appId, anvilUrl, authToken } = options;
|
|
50656
50778
|
const baseUrl = new URL(anvilUrl);
|
|
50657
50779
|
const encodedToken = encodeURIComponent(authToken);
|
|
50658
50780
|
const gitPath = `/git/${appId}.git`;
|
|
@@ -50713,7 +50835,8 @@ var __webpack_exports__ = {};
|
|
|
50713
50835
|
throw errors_createGitError.fetchFailed(e.message);
|
|
50714
50836
|
}
|
|
50715
50837
|
}
|
|
50716
|
-
async function validateViaAnvilServer(git, branchName,
|
|
50838
|
+
async function validateViaAnvilServer(git, branchName, options) {
|
|
50839
|
+
const { appId, anvilUrl, username } = options;
|
|
50717
50840
|
logger_logger.verbose(chalk_source.blue("Validating sync status with Anvil server..."));
|
|
50718
50841
|
const authToken = await auth_getValidAuthToken(anvilUrl, username);
|
|
50719
50842
|
let commitId;
|
|
@@ -51378,7 +51501,7 @@ var __webpack_exports__ = {};
|
|
|
51378
51501
|
</body>
|
|
51379
51502
|
</html>`;
|
|
51380
51503
|
}
|
|
51381
|
-
const CLIENT_ID =
|
|
51504
|
+
const CLIENT_ID = ANVIL_SYNC_CLIENT_ID;
|
|
51382
51505
|
const SCOPES = "apps:read apps:write user:read";
|
|
51383
51506
|
function oauth_login_base64url(buf) {
|
|
51384
51507
|
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -51441,7 +51564,8 @@ var __webpack_exports__ = {};
|
|
|
51441
51564
|
return text;
|
|
51442
51565
|
}
|
|
51443
51566
|
}
|
|
51444
|
-
async function exchangeAuthorizationCodeForTokens(anvilUrl,
|
|
51567
|
+
async function exchangeAuthorizationCodeForTokens(anvilUrl, options) {
|
|
51568
|
+
const { redirectUri, code, codeVerifier } = options;
|
|
51445
51569
|
const tokenResponse = await fetch(`${anvilUrl}/oauth/token`, {
|
|
51446
51570
|
method: "POST",
|
|
51447
51571
|
headers: {
|
|
@@ -51569,7 +51693,11 @@ var __webpack_exports__ = {};
|
|
|
51569
51693
|
const { code, error, recvState } = await codePromise;
|
|
51570
51694
|
if (recvState !== state) throw new Error("Invalid state received from OAuth callback");
|
|
51571
51695
|
if (error) throw new Error(`Error received from OAuth callback: ${error}`);
|
|
51572
|
-
const tokenData = await exchangeAuthorizationCodeForTokens(anvilUrl,
|
|
51696
|
+
const tokenData = await exchangeAuthorizationCodeForTokens(anvilUrl, {
|
|
51697
|
+
redirectUri,
|
|
51698
|
+
code: code,
|
|
51699
|
+
codeVerifier
|
|
51700
|
+
});
|
|
51573
51701
|
return login(anvilUrl, {
|
|
51574
51702
|
access_token: tokenData.access_token,
|
|
51575
51703
|
refresh_token: tokenData.refresh_token,
|
|
@@ -52309,7 +52437,6 @@ var __webpack_exports__ = {};
|
|
|
52309
52437
|
getValidAuthToken: auth_getValidAuthToken,
|
|
52310
52438
|
validateAppId: validateAppId,
|
|
52311
52439
|
listAppsForCheckout: listAppsForCheckout,
|
|
52312
|
-
runInteractiveLoginFlow: runInteractiveLoginFlow,
|
|
52313
52440
|
clone: async (repoUrl, destinationPath, options)=>{
|
|
52314
52441
|
const cloneArgs = [];
|
|
52315
52442
|
if (options?.branch) cloneArgs.push("--branch", options.branch);
|
|
@@ -52322,9 +52449,6 @@ var __webpack_exports__ = {};
|
|
|
52322
52449
|
},
|
|
52323
52450
|
hardenCheckoutGitAuth: hardenCheckoutGitAuth
|
|
52324
52451
|
};
|
|
52325
|
-
function isInteractiveSession() {
|
|
52326
|
-
return !!(process.stdin.isTTY && process.stdout.isTTY);
|
|
52327
|
-
}
|
|
52328
52452
|
function parseCheckoutInput(input) {
|
|
52329
52453
|
const trimmed = input.trim();
|
|
52330
52454
|
if (!trimmed) throw new Error("Input is required.");
|
|
@@ -52388,7 +52512,17 @@ var __webpack_exports__ = {};
|
|
|
52388
52512
|
name: "Cancel",
|
|
52389
52513
|
value: null
|
|
52390
52514
|
});
|
|
52391
|
-
return logger_logger.select("Multiple logged-in Anvil URLs found. Which one would you like to use?", choices, decision.urls[0]
|
|
52515
|
+
return logger_logger.select("Multiple logged-in Anvil URLs found. Which one would you like to use?", choices, decision.urls[0], {
|
|
52516
|
+
action: "`anvil checkout` URL selection",
|
|
52517
|
+
nonInteractiveHint: `Use --url <ANVIL_URL>. Available URLs: ${decision.urls.join(", ")}.`
|
|
52518
|
+
});
|
|
52519
|
+
}
|
|
52520
|
+
function resolveCheckoutUrlForApi(explicitUrl, parsedUrl) {
|
|
52521
|
+
if (explicitUrl) return normalizeAnvilUrl(explicitUrl);
|
|
52522
|
+
if (parsedUrl) return normalizeAnvilUrl(parsedUrl);
|
|
52523
|
+
const decision = decideFallbackUrl(void 0);
|
|
52524
|
+
if ("available-multiple" === decision.source) throw new Error(`Multiple logged-in Anvil URLs found: ${decision.urls.join(", ")}. Use --url <ANVIL_URL> to choose one.`);
|
|
52525
|
+
return decision.url;
|
|
52392
52526
|
}
|
|
52393
52527
|
async function isPathInsideGitRepo(targetPath) {
|
|
52394
52528
|
const resolved = external_path_default().resolve(targetPath);
|
|
@@ -52428,11 +52562,17 @@ var __webpack_exports__ = {};
|
|
|
52428
52562
|
logger_logger.verbose(chalk_source.cyan("Checking auth token for: ") + chalk_source.bold(username ? `${username} @ ${anvilUrl}` : anvilUrl));
|
|
52429
52563
|
return await deps.getValidAuthToken(anvilUrl, username);
|
|
52430
52564
|
} catch (e) {
|
|
52431
|
-
|
|
52432
|
-
|
|
52565
|
+
throw errors_createAuthError.required(`Not logged in to ${anvilUrl}. Run 'anvil login ${anvilUrl}' and retry.`);
|
|
52566
|
+
}
|
|
52567
|
+
}
|
|
52568
|
+
async function ensureCheckoutAuthTokenInteractive(anvilUrl, username, deps = defaultCheckoutDeps) {
|
|
52569
|
+
try {
|
|
52570
|
+
return await ensureCheckoutAuthToken(anvilUrl, username, deps);
|
|
52571
|
+
} catch (e) {
|
|
52572
|
+
assertCanPrompt("`anvil checkout` login prompt", `Run 'anvil login ${anvilUrl}' before checkout.`);
|
|
52433
52573
|
const shouldLogin = await logger_logger.confirm(`Not logged in to ${anvilUrl}. Log in now?`, true);
|
|
52434
|
-
if (!shouldLogin) throw
|
|
52435
|
-
await
|
|
52574
|
+
if (!shouldLogin) throw e;
|
|
52575
|
+
await runInteractiveLoginFlow(anvilUrl);
|
|
52436
52576
|
return deps.getValidAuthToken(anvilUrl, username);
|
|
52437
52577
|
}
|
|
52438
52578
|
}
|
|
@@ -52444,8 +52584,6 @@ var __webpack_exports__ = {};
|
|
|
52444
52584
|
logger_logger.verbose(chalk_source.cyan("Auto-selected account: ") + chalk_source.bold(accounts[0]));
|
|
52445
52585
|
return accounts[0];
|
|
52446
52586
|
}
|
|
52447
|
-
const interactive = process.stdin.isTTY && process.stdout.isTTY;
|
|
52448
|
-
if (!interactive) throw new Error(`Multiple accounts found for ${anvilUrl}. Use --user <USERNAME> to choose one.`);
|
|
52449
52587
|
const choices = accounts.map((acct)=>({
|
|
52450
52588
|
name: acct,
|
|
52451
52589
|
value: acct
|
|
@@ -52454,38 +52592,33 @@ var __webpack_exports__ = {};
|
|
|
52454
52592
|
name: "Cancel",
|
|
52455
52593
|
value: null
|
|
52456
52594
|
});
|
|
52457
|
-
return logger_logger.select(`Multiple accounts found for ${anvilUrl}. Which account should be used for checkout?`, choices, accounts[0]
|
|
52595
|
+
return logger_logger.select(`Multiple accounts found for ${anvilUrl}. Which account should be used for checkout?`, choices, accounts[0], {
|
|
52596
|
+
action: "`anvil checkout` account selection",
|
|
52597
|
+
nonInteractiveHint: `Use --user <USERNAME>. Available accounts: ${accounts.join(", ")}.`
|
|
52598
|
+
});
|
|
52599
|
+
}
|
|
52600
|
+
function resolveCheckoutUsernameForApi(anvilUrl, explicitUsername) {
|
|
52601
|
+
if (explicitUsername) return explicitUsername;
|
|
52602
|
+
const accounts = auth_getAccountsForUrl(anvilUrl);
|
|
52603
|
+
if (0 === accounts.length) return;
|
|
52604
|
+
if (1 === accounts.length) return accounts[0];
|
|
52605
|
+
throw new Error(`Multiple accounts found for ${anvilUrl}: ${accounts.join(", ")}. Use --user <USERNAME> to choose one.`);
|
|
52458
52606
|
}
|
|
52459
52607
|
async function executeCheckout(options, deps = defaultCheckoutDeps) {
|
|
52460
52608
|
let checkoutInput = options.input?.trim();
|
|
52461
|
-
|
|
52462
|
-
let preselectedUsername;
|
|
52463
|
-
if (!checkoutInput) {
|
|
52464
|
-
if (!isInteractiveSession()) throw new Error("`anvil checkout` without arguments requires an interactive TTY. Pass APP_ID or URL explicitly in non-interactive mode.");
|
|
52465
|
-
const selectedUrl = await resolveCheckoutUrl(options.url);
|
|
52466
|
-
if (!selectedUrl) return void logger_logger.info("Checkout cancelled.");
|
|
52467
|
-
preselectedAnvilUrl = selectedUrl;
|
|
52468
|
-
const selectedUsername = await resolveCheckoutUsername(selectedUrl, options.user);
|
|
52469
|
-
if (null === selectedUsername) return void logger_logger.info("Checkout cancelled.");
|
|
52470
|
-
preselectedUsername = selectedUsername || void 0;
|
|
52471
|
-
const selectedInput = await selectAppForCheckout(selectedUrl, preselectedUsername, deps, options.query);
|
|
52472
|
-
if (!selectedInput) return void logger_logger.info("Checkout cancelled.");
|
|
52473
|
-
checkoutInput = selectedInput;
|
|
52474
|
-
}
|
|
52609
|
+
if (!checkoutInput) throw new Error("Checkout input is required. Pass an app ID, editor URL, or /git URL explicitly.");
|
|
52475
52610
|
logger_logger.verbose(chalk_source.cyan("Checkout input: ") + chalk_source.bold(checkoutInput));
|
|
52476
52611
|
const parsed = parseCheckoutInput(checkoutInput);
|
|
52477
52612
|
logger_logger.verbose(chalk_source.cyan("Resolved app ID: ") + chalk_source.bold(parsed.appId));
|
|
52478
|
-
const anvilUrl =
|
|
52479
|
-
if (!anvilUrl)
|
|
52480
|
-
const resolvedUsername =
|
|
52481
|
-
if (null === resolvedUsername) return void logger_logger.info("Checkout cancelled.");
|
|
52613
|
+
const anvilUrl = resolveCheckoutUrlForApi(options.url, parsed.detectedUrl);
|
|
52614
|
+
if (!anvilUrl) throw new Error("Anvil URL is required. Use --url <ANVIL_URL> or pass an input URL containing the host.");
|
|
52615
|
+
const resolvedUsername = resolveCheckoutUsernameForApi(anvilUrl, options.user);
|
|
52482
52616
|
if (resolvedUsername) logger_logger.verbose(chalk_source.cyan("Using account: ") + chalk_source.bold(resolvedUsername));
|
|
52483
52617
|
else logger_logger.verbose(chalk_source.cyan("No account preselected; resolving after auth token lookup."));
|
|
52484
52618
|
const authToken = await ensureCheckoutAuthToken(anvilUrl, resolvedUsername, deps);
|
|
52485
52619
|
let checkoutUsername = resolvedUsername;
|
|
52486
52620
|
if (!checkoutUsername) {
|
|
52487
|
-
const inferredUsername =
|
|
52488
|
-
if (null === inferredUsername) return void logger_logger.info("Checkout cancelled.");
|
|
52621
|
+
const inferredUsername = resolveCheckoutUsernameForApi(anvilUrl, void 0);
|
|
52489
52622
|
if (!inferredUsername) throw new Error(`Could not determine account for ${anvilUrl}. Use --user <USERNAME> so checkout can bind repository credentials.`);
|
|
52490
52623
|
checkoutUsername = inferredUsername;
|
|
52491
52624
|
}
|
|
@@ -52505,8 +52638,6 @@ var __webpack_exports__ = {};
|
|
|
52505
52638
|
if (options.branch) logger_logger.verbose(chalk_source.cyan("Requested branch: ") + chalk_source.bold(options.branch));
|
|
52506
52639
|
if ("number" == typeof options.depth) logger_logger.verbose(chalk_source.cyan("Clone depth: ") + chalk_source.bold(String(options.depth)));
|
|
52507
52640
|
if (options.singleBranch) logger_logger.verbose(chalk_source.cyan("Single-branch clone enabled"));
|
|
52508
|
-
logger_logger.progress("checkout", `Checking out app ${parsed.appId} from ${anvilUrl}`);
|
|
52509
|
-
logger_logger.info(chalk_source.gray(` Destination directory: ${destinationDisplay}`));
|
|
52510
52641
|
await deps.clone(cloneUrl, destinationPath, {
|
|
52511
52642
|
branch: options.branch,
|
|
52512
52643
|
depth: options.depth,
|
|
@@ -52528,14 +52659,57 @@ var __webpack_exports__ = {};
|
|
|
52528
52659
|
} catch (e) {
|
|
52529
52660
|
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.`);
|
|
52530
52661
|
}
|
|
52531
|
-
|
|
52662
|
+
return {
|
|
52663
|
+
appId: parsed.appId,
|
|
52664
|
+
appName: validation.app_name,
|
|
52665
|
+
anvilUrl,
|
|
52666
|
+
destinationPath,
|
|
52667
|
+
destinationDisplay,
|
|
52668
|
+
username: checkoutUsername,
|
|
52669
|
+
remoteName
|
|
52670
|
+
};
|
|
52671
|
+
}
|
|
52672
|
+
async function executeCheckoutInteractive(options, deps = defaultCheckoutDeps) {
|
|
52673
|
+
let checkoutInput = options.input?.trim();
|
|
52674
|
+
let preselectedAnvilUrl;
|
|
52675
|
+
let preselectedUsername;
|
|
52676
|
+
if (!checkoutInput) {
|
|
52677
|
+
assertCanPrompt("`anvil checkout` without arguments", "Pass an app ID, editor URL, or /git URL. Use --url <ANVIL_URL> and --user <USERNAME> if needed.");
|
|
52678
|
+
const selectedUrl = await resolveCheckoutUrl(options.url);
|
|
52679
|
+
if (!selectedUrl) return void logger_logger.info("Checkout cancelled.");
|
|
52680
|
+
preselectedAnvilUrl = selectedUrl;
|
|
52681
|
+
const selectedUsername = await resolveCheckoutUsername(selectedUrl, options.user);
|
|
52682
|
+
if (null === selectedUsername) return void logger_logger.info("Checkout cancelled.");
|
|
52683
|
+
preselectedUsername = selectedUsername || void 0;
|
|
52684
|
+
const selectedInput = await selectAppForCheckout(selectedUrl, preselectedUsername, deps, options.query);
|
|
52685
|
+
if (!selectedInput) return void logger_logger.info("Checkout cancelled.");
|
|
52686
|
+
checkoutInput = selectedInput;
|
|
52687
|
+
}
|
|
52688
|
+
logger_logger.verbose(chalk_source.cyan("Checkout input: ") + chalk_source.bold(checkoutInput));
|
|
52689
|
+
const parsed = parseCheckoutInput(checkoutInput);
|
|
52690
|
+
logger_logger.verbose(chalk_source.cyan("Resolved app ID: ") + chalk_source.bold(parsed.appId));
|
|
52691
|
+
const anvilUrl = preselectedAnvilUrl || await resolveCheckoutUrl(options.url, parsed.detectedUrl);
|
|
52692
|
+
if (!anvilUrl) return void logger_logger.info("Checkout cancelled.");
|
|
52693
|
+
const resolvedUsername = preselectedUsername || await resolveCheckoutUsername(anvilUrl, options.user);
|
|
52694
|
+
if (null === resolvedUsername) return void logger_logger.info("Checkout cancelled.");
|
|
52695
|
+
if (resolvedUsername) logger_logger.verbose(chalk_source.cyan("Using account: ") + chalk_source.bold(resolvedUsername));
|
|
52696
|
+
else logger_logger.verbose(chalk_source.cyan("No account preselected; resolving after auth token lookup."));
|
|
52697
|
+
await ensureCheckoutAuthTokenInteractive(anvilUrl, resolvedUsername, deps);
|
|
52698
|
+
logger_logger.progress("checkout", `Checking out app ${parsed.appId} from ${anvilUrl}`);
|
|
52699
|
+
const result = await executeCheckout({
|
|
52700
|
+
...options,
|
|
52701
|
+
input: checkoutInput,
|
|
52702
|
+
url: anvilUrl,
|
|
52703
|
+
user: resolvedUsername || options.user
|
|
52704
|
+
}, deps);
|
|
52705
|
+
logger_logger.progressEnd("checkout", `Checked out ${result.appId} into ${result.destinationDisplay}`);
|
|
52532
52706
|
const preferredEditor = String(getConfig("preferredEditor") || "").trim();
|
|
52533
52707
|
const preferredEditorCommand = preferredEditor ? getPreferredEditorCommand(preferredEditor) : "";
|
|
52534
52708
|
if (options.open) {
|
|
52535
|
-
await checkout_openPathInEditorOrDefault(destinationPath, preferredEditorCommand);
|
|
52536
|
-
logger_logger.info(chalk_source.gray(`Opened ${destinationDisplay}`));
|
|
52709
|
+
await checkout_openPathInEditorOrDefault(result.destinationPath, preferredEditorCommand);
|
|
52710
|
+
logger_logger.info(chalk_source.gray(`Opened ${result.destinationDisplay}`));
|
|
52537
52711
|
}
|
|
52538
|
-
if (preferredEditorCommand && !options.open) if (isCommandAvailable(preferredEditorCommand)) logger_logger.info(chalk_source.cyan(`Next: ${preferredEditorCommand} ${destinationDisplay}`));
|
|
52712
|
+
if (preferredEditorCommand && !options.open) if (isCommandAvailable(preferredEditorCommand)) logger_logger.info(chalk_source.cyan(`Next: ${preferredEditorCommand} ${result.destinationDisplay}`));
|
|
52539
52713
|
else logger_logger.warn(`Preferred editor command '${preferredEditorCommand}' was not found in PATH. Run 'anvil configure' to choose an installed editor.`);
|
|
52540
52714
|
}
|
|
52541
52715
|
async function checkout_openPathInEditorOrDefault(destinationPath, preferredEditorCommand, deps) {
|
|
@@ -52546,7 +52720,7 @@ var __webpack_exports__ = {};
|
|
|
52546
52720
|
try {
|
|
52547
52721
|
const globalOptions = command?.optsWithGlobals() || options || {};
|
|
52548
52722
|
if ("number" == typeof options?.depth && (!Number.isFinite(options.depth) || options.depth <= 0)) throw new Error("--depth must be a positive integer");
|
|
52549
|
-
await
|
|
52723
|
+
await executeCheckoutInteractive({
|
|
52550
52724
|
input,
|
|
52551
52725
|
directory,
|
|
52552
52726
|
open: options?.open,
|
|
@@ -52569,7 +52743,8 @@ var __webpack_exports__ = {};
|
|
|
52569
52743
|
checkoutCommand.addHelpText("after", "\n" + chalk_source.bold("Examples:") + '\n anvil checkout http://localhost:3000/build/apps/APPID/code/assets/theme.css\n anvil checkout https://anvil.works/git/APPID.git\n anvil checkout APPID --url anvil.works\n anvil checkout APPID --branch master --depth 1 --single-branch\n anvil checkout APPID -O # open editor/file browser after checkout\n anvil checkout APPID my-local-folder --force\n anvil checkout # interactive search/select app list\n anvil checkout -Q "dashboard" # preseed picker search\n');
|
|
52570
52744
|
}
|
|
52571
52745
|
const DEFAULT_ANVIL_URL = resolveAnvilUrl();
|
|
52572
|
-
async function syncToLatest(repoPath, appId,
|
|
52746
|
+
async function syncToLatest(repoPath, appId, options) {
|
|
52747
|
+
const { anvilUrl, authToken, currentBranch, username } = options;
|
|
52573
52748
|
try {
|
|
52574
52749
|
const git = esm_default(repoPath);
|
|
52575
52750
|
const commitId = (await git.revparse([
|
|
@@ -52593,7 +52768,8 @@ var __webpack_exports__ = {};
|
|
|
52593
52768
|
throw errors_createGitError.commandFailed("sync", e instanceof Error ? e.message : String(e));
|
|
52594
52769
|
}
|
|
52595
52770
|
}
|
|
52596
|
-
async function api_watch(repoPath, appId,
|
|
52771
|
+
async function api_watch(repoPath, appId, options = {}) {
|
|
52772
|
+
const { anvilUrl = DEFAULT_ANVIL_URL, stagedOnly = false, username } = options;
|
|
52597
52773
|
repoPath = external_path_default().resolve(repoPath);
|
|
52598
52774
|
const authToken = await auth_getValidAuthToken(anvilUrl, username);
|
|
52599
52775
|
await verifyAuth(authToken, anvilUrl);
|
|
@@ -52620,7 +52796,11 @@ var __webpack_exports__ = {};
|
|
|
52620
52796
|
}
|
|
52621
52797
|
logger_logger.verbose(chalk_source.cyan("Current branch: ") + chalk_source.bold(currentBranch));
|
|
52622
52798
|
logger_logger.verbose(chalk_source.cyan("Current commit ID: ") + chalk_source.gray(commitId));
|
|
52623
|
-
const syncStatus = await validateBranchSyncStatus(git, currentBranch,
|
|
52799
|
+
const syncStatus = await validateBranchSyncStatus(git, currentBranch, {
|
|
52800
|
+
appId,
|
|
52801
|
+
anvilUrl,
|
|
52802
|
+
username
|
|
52803
|
+
});
|
|
52624
52804
|
let hasUncommittedChanges = false;
|
|
52625
52805
|
try {
|
|
52626
52806
|
const status = await git.status();
|
|
@@ -52969,7 +53149,11 @@ var __webpack_exports__ = {};
|
|
|
52969
53149
|
async function recheckSyncStatus(previousCategory, previousBranch, options) {
|
|
52970
53150
|
try {
|
|
52971
53151
|
logger_logger.progress("verify", "Verifying repository status...");
|
|
52972
|
-
const freshSession = await api_watch(options.repoPath, options.appId,
|
|
53152
|
+
const freshSession = await api_watch(options.repoPath, options.appId, {
|
|
53153
|
+
anvilUrl: options.anvilUrl,
|
|
53154
|
+
stagedOnly: options.stagedOnly,
|
|
53155
|
+
username: options.username
|
|
53156
|
+
});
|
|
52973
53157
|
logger_logger.progressEnd("verify");
|
|
52974
53158
|
const currentCategory = getSyncStateCategory(freshSession.syncStatus);
|
|
52975
53159
|
const currentBranch = freshSession.getBranchName() || "master";
|
|
@@ -52988,7 +53172,11 @@ var __webpack_exports__ = {};
|
|
|
52988
53172
|
async function recreateSessionAndValidate(options) {
|
|
52989
53173
|
logger_logger.progress("init", "Restarting watch session...");
|
|
52990
53174
|
try {
|
|
52991
|
-
const newSession = await api_watch(options.repoPath, options.appId,
|
|
53175
|
+
const newSession = await api_watch(options.repoPath, options.appId, {
|
|
53176
|
+
anvilUrl: options.anvilUrl,
|
|
53177
|
+
stagedOnly: options.stagedOnly,
|
|
53178
|
+
username: options.username
|
|
53179
|
+
});
|
|
52992
53180
|
logger_logger.progressEnd("init");
|
|
52993
53181
|
return await checkSyncStatusAndStart(newSession, options);
|
|
52994
53182
|
} catch (e) {
|
|
@@ -53201,7 +53389,12 @@ var __webpack_exports__ = {};
|
|
|
53201
53389
|
}
|
|
53202
53390
|
logger_logger.progress("sync-latest", "Syncing to latest version from Anvil...");
|
|
53203
53391
|
try {
|
|
53204
|
-
const newCommitId = await syncToLatest(options.repoPath, options.appId,
|
|
53392
|
+
const newCommitId = await syncToLatest(options.repoPath, options.appId, {
|
|
53393
|
+
anvilUrl: options.anvilUrl,
|
|
53394
|
+
authToken,
|
|
53395
|
+
currentBranch: branchName,
|
|
53396
|
+
username: options.username
|
|
53397
|
+
});
|
|
53205
53398
|
logger_logger.progressEnd("sync-latest", `Synced to latest version: ${newCommitId.substring(0, 8)}`);
|
|
53206
53399
|
} catch (e) {
|
|
53207
53400
|
logger_logger.progressEnd("sync-latest", "Failed");
|
|
@@ -53228,7 +53421,11 @@ var __webpack_exports__ = {};
|
|
|
53228
53421
|
if (actualBranch !== newBranch) logger_logger.verbose(chalk_source.yellow(`Branch changed again to ${chalk_source.bold(actualBranch)}, using that instead`));
|
|
53229
53422
|
logger_logger.progress("init", "Initializing watch session...");
|
|
53230
53423
|
try {
|
|
53231
|
-
const newSession = await api_watch(repoPath, appId,
|
|
53424
|
+
const newSession = await api_watch(repoPath, appId, {
|
|
53425
|
+
anvilUrl,
|
|
53426
|
+
stagedOnly,
|
|
53427
|
+
username: options.username
|
|
53428
|
+
});
|
|
53232
53429
|
logger_logger.progressEnd("init");
|
|
53233
53430
|
const started = await checkSyncStatusAndStart(newSession, options);
|
|
53234
53431
|
if (!started) process.exit(0);
|
|
@@ -53441,7 +53638,11 @@ var __webpack_exports__ = {};
|
|
|
53441
53638
|
if (stagedOnly) logger_logger.info(chalk_source.yellow("▸ Staged-only mode: Only staged changes will be synced"));
|
|
53442
53639
|
if (autoMode) logger_logger.info(chalk_source.cyan("▸ Auto mode: Will automatically restart on branch changes and sync when behind"));
|
|
53443
53640
|
logger_logger.progress("init", "Initializing watch session...");
|
|
53444
|
-
const session = await api_watch(repoPath, finalAppId,
|
|
53641
|
+
const session = await api_watch(repoPath, finalAppId, {
|
|
53642
|
+
anvilUrl,
|
|
53643
|
+
stagedOnly,
|
|
53644
|
+
username
|
|
53645
|
+
});
|
|
53445
53646
|
logger_logger.progressEnd("init");
|
|
53446
53647
|
if (openAfterValidation) await openWatchPath(resolveWatchOpenPath(repoPath));
|
|
53447
53648
|
logger_logger.verbose(chalk_source.blue("Watching for file changes..."));
|
|
@@ -53897,11 +54098,8 @@ var __webpack_exports__ = {};
|
|
|
53897
54098
|
if (1 === accounts.length) return accounts[0];
|
|
53898
54099
|
return `${accounts.length} accounts`;
|
|
53899
54100
|
}
|
|
53900
|
-
function configure_isInteractiveSession() {
|
|
53901
|
-
return !!(process.stdin.isTTY && process.stdout.isTTY);
|
|
53902
|
-
}
|
|
53903
54101
|
async function runConfigureFlow(version, deps = configure_defaultDeps) {
|
|
53904
|
-
|
|
54102
|
+
assertCanPrompt("`anvil configure`", "Use `anvil config set anvilUrl <URL>`, `anvil config set preferredEditor <COMMAND>`, `anvil config set verbose <true|false>`, and `anvil login <URL>` instead.");
|
|
53905
54103
|
console.log();
|
|
53906
54104
|
logger_logger.info(chalk_source.cyan.bold("Anvil Configuration"));
|
|
53907
54105
|
console.log();
|