@anvil-works/anvil-cli 0.8.0-canary.21 → 0.8.0-canary.23

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.
Files changed (54) hide show
  1. package/README.md +33 -1
  2. package/dist/CLILogger.d.ts.map +1 -1
  3. package/dist/api.d.ts +3 -1
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/cli.d.ts +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +18216 -17213
  8. package/dist/cliProgram.d.ts +4 -0
  9. package/dist/cliProgram.d.ts.map +1 -0
  10. package/dist/commands/appDetection.d.ts +68 -1
  11. package/dist/commands/appDetection.d.ts.map +1 -1
  12. package/dist/commands/checkout.d.ts +1 -0
  13. package/dist/commands/checkout.d.ts.map +1 -1
  14. package/dist/commands/create.d.ts +52 -0
  15. package/dist/commands/create.d.ts.map +1 -0
  16. package/dist/commands/db.d.ts.map +1 -1
  17. package/dist/commands/deps.d.ts.map +1 -1
  18. package/dist/commands/env.d.ts +3 -1
  19. package/dist/commands/env.d.ts.map +1 -1
  20. package/dist/commands/index.d.ts +1 -0
  21. package/dist/commands/index.d.ts.map +1 -1
  22. package/dist/commands/repl.d.ts.map +1 -1
  23. package/dist/commands/secret.d.ts.map +1 -1
  24. package/dist/commands/validate.d.ts +11 -0
  25. package/dist/commands/validate.d.ts.map +1 -0
  26. package/dist/commands/watch.d.ts +1 -25
  27. package/dist/commands/watch.d.ts.map +1 -1
  28. package/dist/config.d.ts +3 -1
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/formTemplateValidation.d.ts.map +1 -1
  31. package/dist/index.js +304 -111
  32. package/dist/program.d.ts +2 -9
  33. package/dist/program.d.ts.map +1 -1
  34. package/dist/programBase.d.ts +5 -0
  35. package/dist/programBase.d.ts.map +1 -0
  36. package/dist/services/anvil-api.d.ts +11 -0
  37. package/dist/services/anvil-api.d.ts.map +1 -1
  38. package/dist/services/db.d.ts +2 -0
  39. package/dist/services/db.d.ts.map +1 -1
  40. package/dist/services/deps.d.ts +2 -23
  41. package/dist/services/deps.d.ts.map +1 -1
  42. package/dist/services/depsCache.d.ts +25 -0
  43. package/dist/services/depsCache.d.ts.map +1 -0
  44. package/dist/services/environment.d.ts +4 -0
  45. package/dist/services/environment.d.ts.map +1 -1
  46. package/dist/services/path-open.d.ts +1 -0
  47. package/dist/services/path-open.d.ts.map +1 -1
  48. package/dist/services/repl.d.ts +2 -0
  49. package/dist/services/repl.d.ts.map +1 -1
  50. package/dist/services/secret.d.ts +4 -0
  51. package/dist/services/secret.d.ts.map +1 -1
  52. package/dist/validatePython.d.ts +5 -5
  53. package/dist/validatePython.d.ts.map +1 -1
  54. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -6705,6 +6705,10 @@ var __webpack_modules__ = {
6705
6705
  "use strict";
6706
6706
  module.exports = require("fs");
6707
6707
  },
6708
+ ora (module) {
6709
+ "use strict";
6710
+ module.exports = require("ora");
6711
+ },
6708
6712
  os (module) {
6709
6713
  "use strict";
6710
6714
  module.exports = require("os");
@@ -7373,6 +7377,7 @@ var __webpack_exports__ = {};
7373
7377
  AppIdWithContext: ()=>anvil_api_namespaceObject.AppIdWithContext,
7374
7378
  inspectCredentialHelperCommand: ()=>inspectCredentialHelperCommand,
7375
7379
  executeCheckout: ()=>executeCheckout,
7380
+ executeCreate: ()=>executeCreate,
7376
7381
  validateCheckoutDestination: ()=>validateCheckoutDestination,
7377
7382
  DeviceAuthorizationResponse: ()=>oauth_login_namespaceObject.DeviceAuthorizationResponse,
7378
7383
  OAuthTokenResponse: ()=>oauth_login_namespaceObject.OAuthTokenResponse,
@@ -7446,7 +7451,9 @@ var __webpack_exports__ = {};
7446
7451
  setInMemoryTokens: ()=>setInMemoryTokens,
7447
7452
  validateAppId: ()=>anvil_api_validateAppId,
7448
7453
  pollDeviceAuthorization: ()=>pollDeviceAuthorization,
7454
+ createAnvilApp: ()=>createAnvilApp,
7449
7455
  getValidAuthToken: ()=>auth_getValidAuthToken,
7456
+ CreatedAnvilApp: ()=>anvil_api_namespaceObject.CreatedAnvilApp,
7450
7457
  watch: ()=>src_api_watch,
7451
7458
  deleteConfig: ()=>deleteConfig,
7452
7459
  installModelTokenHelperScript: ()=>installModelTokenHelperScript,
@@ -7462,11 +7469,12 @@ var __webpack_exports__ = {};
7462
7469
  CheckoutResult: ()=>checkout_namespaceObject.CheckoutResult,
7463
7470
  ParsedCheckoutInput: ()=>checkout_namespaceObject.ParsedCheckoutInput,
7464
7471
  parseCredentialHelperCommand: ()=>parseCredentialHelperCommand,
7465
- MODEL_TOKEN_LOCK_TIMEOUT_MS: ()=>MODEL_TOKEN_LOCK_TIMEOUT_MS,
7472
+ CreateCheckoutError: ()=>CreateCheckoutError,
7466
7473
  GetValidAuthTokenOptions: ()=>auth_namespaceObject.GetValidAuthTokenOptions,
7467
- clearInMemoryTokens: ()=>clearInMemoryTokens,
7474
+ MODEL_TOKEN_LOCK_TIMEOUT_MS: ()=>MODEL_TOKEN_LOCK_TIMEOUT_MS,
7468
7475
  getDefaultDestinationDirectory: ()=>getDefaultDestinationDirectory,
7469
7476
  AUTH_FILE_LOCK_DEFAULTS: ()=>AUTH_FILE_LOCK_DEFAULTS,
7477
+ clearInMemoryTokens: ()=>clearInMemoryTokens,
7470
7478
  lookupByCommit: ()=>lookupByCommit,
7471
7479
  AppIdCandidate: ()=>anvil_api_namespaceObject.AppIdCandidate,
7472
7480
  verifyAuth: ()=>auth_verifyAuth
@@ -7483,6 +7491,7 @@ var __webpack_exports__ = {};
7483
7491
  P$: ()=>config_isCommandAvailable,
7484
7492
  n: ()=>config_isDevMode,
7485
7493
  Wj: ()=>config_isTestMode,
7494
+ Wc: ()=>config_normalizeAnvilOrigin,
7486
7495
  Vl: ()=>config_normalizeAnvilUrl,
7487
7496
  PW: ()=>parseConfigSetValue,
7488
7497
  cx: ()=>preferredEditors,
@@ -7511,19 +7520,20 @@ var __webpack_exports__ = {};
7511
7520
  var anvil_api_namespaceObject = {};
7512
7521
  __webpack_require__.r(anvil_api_namespaceObject);
7513
7522
  __webpack_require__.d(anvil_api_namespaceObject, {
7514
- lx: ()=>anvil_api_detectAppIdsByCommitLookup,
7515
- NZ: ()=>anvil_api_detectAppIdsFromAllRemotes,
7516
- rZ: ()=>anvil_api_filterCandidates,
7517
- T_: ()=>anvil_api_formatCandidateLabel,
7518
- OI: ()=>anvil_api_getGitFetchUrl,
7519
- _r: ()=>anvil_api_getGitPushUrl,
7520
- CA: ()=>getLatestVersion,
7521
- $0: ()=>getWebSocketUrl,
7522
- A1: ()=>listAppsForCheckout,
7523
- l9: ()=>lookupByCommit,
7524
- Wj: ()=>anvil_api_lookupRemoteInfoForAppId,
7525
- Us: ()=>saveUpdates,
7526
- zW: ()=>anvil_api_validateAppId
7523
+ createAnvilApp: ()=>createAnvilApp,
7524
+ detectAppIdsByCommitLookup: ()=>anvil_api_detectAppIdsByCommitLookup,
7525
+ detectAppIdsFromAllRemotes: ()=>anvil_api_detectAppIdsFromAllRemotes,
7526
+ filterCandidates: ()=>anvil_api_filterCandidates,
7527
+ formatCandidateLabel: ()=>anvil_api_formatCandidateLabel,
7528
+ getGitFetchUrl: ()=>anvil_api_getGitFetchUrl,
7529
+ getGitPushUrl: ()=>anvil_api_getGitPushUrl,
7530
+ getLatestVersion: ()=>getLatestVersion,
7531
+ getWebSocketUrl: ()=>getWebSocketUrl,
7532
+ listAppsForCheckout: ()=>listAppsForCheckout,
7533
+ lookupByCommit: ()=>lookupByCommit,
7534
+ lookupRemoteInfoForAppId: ()=>anvil_api_lookupRemoteInfoForAppId,
7535
+ saveUpdates: ()=>saveUpdates,
7536
+ validateAppId: ()=>anvil_api_validateAppId
7527
7537
  });
7528
7538
  var validators_namespaceObject = {};
7529
7539
  __webpack_require__.r(validators_namespaceObject);
@@ -7553,6 +7563,7 @@ var __webpack_exports__ = {};
7553
7563
  A9: ()=>isDirectoryNonEmpty,
7554
7564
  oU: ()=>isPathInsideGitRepo,
7555
7565
  Qx: ()=>parseCheckoutInput,
7566
+ B6: ()=>resolveCheckoutUrlForApi,
7556
7567
  KV: ()=>sanitizeDirectoryName,
7557
7568
  Bc: ()=>validateCheckoutDestination
7558
7569
  });
@@ -13109,12 +13120,25 @@ var __webpack_exports__ = {};
13109
13120
  if (!urlInput || "string" != typeof urlInput) return urlInput;
13110
13121
  let url = urlInput.trim();
13111
13122
  url = url.replace(/\/+$/, "");
13112
- if ("localhost" === url || url.startsWith("localhost:")) return "http://localhost:3000";
13113
- if ("http://localhost" === url || url.startsWith("http://localhost:")) return "http://localhost:3000";
13114
- if ("https://localhost" === url || url.startsWith("https://localhost:")) return "http://localhost:3000";
13115
- if (/^https?:\/\//.test(url)) return url;
13123
+ if ("localhost" === url) return "http://localhost:3000";
13124
+ if (url.startsWith("localhost:")) return `http://${url}`;
13125
+ if (/^https?:\/\//i.test(url)) return url;
13116
13126
  return `https://${url}`;
13117
13127
  }
13128
+ function config_normalizeAnvilOrigin(input) {
13129
+ try {
13130
+ const raw = input.trim();
13131
+ const normalized = config_normalizeAnvilUrl(raw);
13132
+ const url = new URL(raw.includes("://") ? raw : normalized);
13133
+ if (![
13134
+ "http:",
13135
+ "https:"
13136
+ ].includes(url.protocol) || url.username || url.password || "/" !== url.pathname || url.search || url.hash) throw new Error("Invalid origin");
13137
+ return normalized;
13138
+ } catch {
13139
+ throw new Error("Server URL must be an HTTP(S) origin without credentials, a path, query, or fragment.");
13140
+ }
13141
+ }
13118
13142
  function resolveAnvilUrl() {
13119
13143
  const fromConfig = config_getConfig("anvilUrl");
13120
13144
  if ("string" == typeof fromConfig && fromConfig.trim()) return fromConfig.trim();
@@ -14774,6 +14798,39 @@ Promise.resolve()
14774
14798
  function anvil_api_getDefaultAnvilUrl() {
14775
14799
  return resolveAnvilUrl();
14776
14800
  }
14801
+ async function createAnvilApp(options) {
14802
+ let response;
14803
+ try {
14804
+ response = await fetch(`${options.anvilUrl}/ide/api/_/apps`, {
14805
+ method: "POST",
14806
+ headers: {
14807
+ Authorization: `Bearer ${options.authToken}`,
14808
+ "Content-Type": "application/json"
14809
+ },
14810
+ body: JSON.stringify({
14811
+ name: options.name,
14812
+ tags: options.tags
14813
+ })
14814
+ });
14815
+ } catch (error) {
14816
+ throw createNetworkError.network(error.message);
14817
+ }
14818
+ const data = await response.json().catch(()=>({}));
14819
+ if (!response.ok) {
14820
+ if (401 === response.status || 403 === response.status) throw createAuthError.invalid(data.error || "Not authorized to create an app");
14821
+ throw new Error(data.error || `Failed to create app: ${response.status} ${response.statusText}`);
14822
+ }
14823
+ if ("string" != typeof data.id || !data.id) throw new Error("App creation response did not contain an app ID.");
14824
+ return {
14825
+ id: data.id,
14826
+ ..."string" == typeof data.name ? {
14827
+ name: data.name
14828
+ } : {},
14829
+ ...data.tags ? {
14830
+ tags: data.tags
14831
+ } : {}
14832
+ };
14833
+ }
14777
14834
  async function anvil_api_validateAppId(appId, anvilUrl = anvil_api_getDefaultAnvilUrl(), username) {
14778
14835
  const authToken = await auth_getValidAuthToken(anvilUrl, username);
14779
14836
  try {
@@ -14945,14 +15002,15 @@ Promise.resolve()
14945
15002
  try {
14946
15003
  const remotes = await git.getRemotes(true);
14947
15004
  for (const remote of remotes){
14948
- const httpMatch = remote.refs.fetch?.match(/(?:http|https):\/\/(?:[^@]+@)?([^:\/]+)(?::\d+)?\/git\/([A-Z0-9]+)\.git/);
15005
+ const httpMatch = remote.refs.fetch?.match(/(https?):\/\/(?:[^@\/]+@)?([^\/]+)\/git\/([A-Z0-9]+)\.git/);
14949
15006
  if (httpMatch) {
14950
- const [, host, detectedAppId] = httpMatch;
15007
+ const [, scheme, host, detectedAppId] = httpMatch;
15008
+ const origin = new URL(`${scheme}://${host}`).origin;
14951
15009
  out.push({
14952
15010
  appId: detectedAppId,
14953
15011
  source: "remote",
14954
15012
  description: `Git remote '${remote.name}'`,
14955
- detectedUrl: config_normalizeAnvilUrl(host)
15013
+ detectedUrl: config_normalizeAnvilUrl(origin)
14956
15014
  });
14957
15015
  continue;
14958
15016
  }
@@ -15016,6 +15074,29 @@ Promise.resolve()
15016
15074
  }
15017
15075
  const external_fs_promises_namespaceObject = require("fs/promises");
15018
15076
  var external_fs_promises_default = /*#__PURE__*/ __webpack_require__.n(external_fs_promises_namespaceObject);
15077
+ function formatHttpError(prefix, status, body) {
15078
+ if (!body) return `${prefix}: ${status}`;
15079
+ try {
15080
+ const parsed = JSON.parse(body);
15081
+ if ("string" == typeof parsed.error && parsed.error.trim()) return `${prefix}: ${parsed.error} (${status})`;
15082
+ } catch {}
15083
+ return `${prefix}: ${status} ${body}`;
15084
+ }
15085
+ const ANVIL_GITIGNORE_ENTRY = "/.anvil/";
15086
+ async function ensureProjectGitignoreIgnoresAnvilDir(projectRoot) {
15087
+ const rootGitignorePath = external_path_default().join(projectRoot, ".gitignore");
15088
+ try {
15089
+ const existing = await external_fs_.promises.readFile(rootGitignorePath, "utf8");
15090
+ if (existing.includes(ANVIL_GITIGNORE_ENTRY)) return false;
15091
+ const prefix = existing.endsWith("\n") || 0 === existing.length ? "" : "\n";
15092
+ await external_fs_.promises.writeFile(rootGitignorePath, `${existing}${prefix}${ANVIL_GITIGNORE_ENTRY}\n`, "utf8");
15093
+ return true;
15094
+ } catch (error) {
15095
+ if ("ENOENT" !== error.code) throw error;
15096
+ await external_fs_.promises.writeFile(rootGitignorePath, `${ANVIL_GITIGNORE_ENTRY}\n`, "utf8");
15097
+ return true;
15098
+ }
15099
+ }
15019
15100
  function normalizeLineEndings(content) {
15020
15101
  return content.replace(/\r\n/g, "\n");
15021
15102
  }
@@ -15060,32 +15141,67 @@ Promise.resolve()
15060
15141
  html: htmlContent
15061
15142
  };
15062
15143
  }
15063
- function formatHttpError(prefix, status, body) {
15064
- if (!body) return `${prefix}: ${status}`;
15144
+ const ANVIL_DEPS_DIR = ".anvil/deps";
15145
+ const ANVIL_DEPS_MANIFEST = "manifest.json";
15146
+ const DEPS_MANIFEST_VERSION = 3;
15147
+ function depsCache_depsDir(projectRoot) {
15148
+ return external_path_default().join(projectRoot, ANVIL_DEPS_DIR);
15149
+ }
15150
+ function depsManifestPath(projectRoot) {
15151
+ return external_path_default().join(depsCache_depsDir(projectRoot), ANVIL_DEPS_MANIFEST);
15152
+ }
15153
+ function isResolvedDependencyManifestEntry(value) {
15154
+ if (!value || "object" != typeof value) return false;
15155
+ const entry = value;
15156
+ return "string" == typeof entry.app_id && entry.app_id.length > 0 && "string" == typeof entry.commit_id && entry.commit_id.length > 0 && (void 0 === entry.branch || "string" == typeof entry.branch);
15157
+ }
15158
+ function isCachedDependencyManifestEntry(value) {
15159
+ if (!isResolvedDependencyManifestEntry(value)) return false;
15160
+ const entry = value;
15161
+ return "string" == typeof entry.package_name && entry.package_name.length > 0;
15162
+ }
15163
+ function isDepsCacheManifest(value) {
15164
+ if (!value || "object" != typeof value) return false;
15165
+ const manifest = value;
15166
+ return manifest.version === DEPS_MANIFEST_VERSION && "boolean" == typeof manifest.includeDocs && (null === manifest.source_dependencies || Array.isArray(manifest.source_dependencies)) && Array.isArray(manifest.resolved_dependencies) && manifest.resolved_dependencies.every(isResolvedDependencyManifestEntry) && Array.isArray(manifest.cached_dependencies) && manifest.cached_dependencies.every(isCachedDependencyManifestEntry);
15167
+ }
15168
+ async function readDepsCacheManifest(projectRoot) {
15065
15169
  try {
15066
- const parsed = JSON.parse(body);
15067
- if ("string" == typeof parsed.error && parsed.error.trim()) return `${prefix}: ${parsed.error} (${status})`;
15068
- } catch {}
15069
- return `${prefix}: ${status} ${body}`;
15170
+ const raw = await external_fs_promises_default().readFile(depsManifestPath(projectRoot), "utf-8");
15171
+ const parsed = JSON.parse(raw);
15172
+ return isDepsCacheManifest(parsed) ? parsed : void 0;
15173
+ } catch {
15174
+ return;
15175
+ }
15070
15176
  }
15071
- const ANVIL_GITIGNORE_ENTRY = "/.anvil/";
15072
- async function ensureProjectGitignoreIgnoresAnvilDir(projectRoot) {
15073
- const rootGitignorePath = external_path_default().join(projectRoot, ".gitignore");
15177
+ function normalizeAnvilYamlDependenciesFromContent(content) {
15178
+ const parsed = external_js_yaml_default().load(content);
15179
+ if (!parsed || "object" != typeof parsed || !Array.isArray(parsed.dependencies)) return [];
15180
+ return normalizeAnvilYamlDependenciesValue(parsed.dependencies);
15181
+ }
15182
+ function normalizeAnvilYamlDependenciesValue(value) {
15183
+ if (!Array.isArray(value)) return [];
15184
+ return value.map(normalizeForComparison);
15185
+ }
15186
+ async function readAnvilYamlDependencies(projectRoot) {
15074
15187
  try {
15075
- const existing = await external_fs_.promises.readFile(rootGitignorePath, "utf8");
15076
- if (existing.includes(ANVIL_GITIGNORE_ENTRY)) return false;
15077
- const prefix = existing.endsWith("\n") || 0 === existing.length ? "" : "\n";
15078
- await external_fs_.promises.writeFile(rootGitignorePath, `${existing}${prefix}${ANVIL_GITIGNORE_ENTRY}\n`, "utf8");
15079
- return true;
15080
- } catch (error) {
15081
- if ("ENOENT" !== error.code) throw error;
15082
- await external_fs_.promises.writeFile(rootGitignorePath, `${ANVIL_GITIGNORE_ENTRY}\n`, "utf8");
15083
- return true;
15188
+ const content = await external_fs_promises_default().readFile(external_path_default().join(projectRoot, "anvil.yaml"), "utf-8");
15189
+ return normalizeAnvilYamlDependenciesFromContent(content);
15190
+ } catch {
15191
+ return [];
15084
15192
  }
15085
15193
  }
15086
- const ANVIL_DEPS_DIR = ".anvil/deps";
15087
- const ANVIL_DEPS_MANIFEST = "manifest.json";
15088
- const DEPS_MANIFEST_VERSION = 3;
15194
+ function anvilYamlDependenciesEqual(left, right) {
15195
+ return deepEqual(left, right);
15196
+ }
15197
+ function normalizeForComparison(value) {
15198
+ if (Array.isArray(value)) return value.map(normalizeForComparison);
15199
+ if (value && "object" == typeof value) return Object.fromEntries(Object.entries(value).sort(([left], [right])=>left.localeCompare(right)).map(([key, entryValue])=>[
15200
+ key,
15201
+ normalizeForComparison(entryValue)
15202
+ ]));
15203
+ return value;
15204
+ }
15089
15205
  async function fetchAllDependencies(appId, anvilUrl, options = {}) {
15090
15206
  const { commit, includeDocs = true, knownDependencies = [] } = options;
15091
15207
  anvilUrl ??= await auth_resolveAuthAnvilUrl();
@@ -15144,36 +15260,6 @@ Promise.resolve()
15144
15260
  addedGitignoreEntry
15145
15261
  };
15146
15262
  }
15147
- function depsDir(projectRoot) {
15148
- return external_path_default().join(projectRoot, ANVIL_DEPS_DIR);
15149
- }
15150
- function depsManifestPath(projectRoot) {
15151
- return external_path_default().join(depsDir(projectRoot), ANVIL_DEPS_MANIFEST);
15152
- }
15153
- function isResolvedDependencyManifestEntry(value) {
15154
- if (!value || "object" != typeof value) return false;
15155
- const entry = value;
15156
- return "string" == typeof entry.app_id && entry.app_id.length > 0 && "string" == typeof entry.commit_id && entry.commit_id.length > 0 && (void 0 === entry.branch || "string" == typeof entry.branch);
15157
- }
15158
- function isCachedDependencyManifestEntry(value) {
15159
- if (!isResolvedDependencyManifestEntry(value)) return false;
15160
- const entry = value;
15161
- return "string" == typeof entry.package_name && entry.package_name.length > 0;
15162
- }
15163
- function isDepsCacheManifest(value) {
15164
- if (!value || "object" != typeof value) return false;
15165
- const manifest = value;
15166
- return manifest.version === DEPS_MANIFEST_VERSION && "boolean" == typeof manifest.includeDocs && (null === manifest.source_dependencies || Array.isArray(manifest.source_dependencies)) && Array.isArray(manifest.resolved_dependencies) && manifest.resolved_dependencies.every(isResolvedDependencyManifestEntry) && Array.isArray(manifest.cached_dependencies) && manifest.cached_dependencies.every(isCachedDependencyManifestEntry);
15167
- }
15168
- async function readDepsCacheManifest(projectRoot) {
15169
- try {
15170
- const raw = await external_fs_promises_default().readFile(depsManifestPath(projectRoot), "utf-8");
15171
- const parsed = JSON.parse(raw);
15172
- return isDepsCacheManifest(parsed) ? parsed : void 0;
15173
- } catch {
15174
- return;
15175
- }
15176
- }
15177
15263
  async function getKnownDependenciesForCache(projectRoot, includeDocs) {
15178
15264
  const manifest = await readDepsCacheManifest(projectRoot);
15179
15265
  if (!manifest || manifest.includeDocs !== includeDocs) return [];
@@ -15199,34 +15285,6 @@ Promise.resolve()
15199
15285
  ];
15200
15286
  });
15201
15287
  }
15202
- function normalizeAnvilYamlDependenciesFromContent(content) {
15203
- const parsed = external_js_yaml_default().load(content);
15204
- if (!parsed || "object" != typeof parsed || !Array.isArray(parsed.dependencies)) return [];
15205
- return normalizeAnvilYamlDependenciesValue(parsed.dependencies);
15206
- }
15207
- function normalizeAnvilYamlDependenciesValue(value) {
15208
- if (!Array.isArray(value)) return [];
15209
- return value.map(normalizeForComparison);
15210
- }
15211
- async function readAnvilYamlDependencies(projectRoot) {
15212
- try {
15213
- const content = await external_fs_promises_default().readFile(external_path_default().join(projectRoot, "anvil.yaml"), "utf-8");
15214
- return normalizeAnvilYamlDependenciesFromContent(content);
15215
- } catch {
15216
- return [];
15217
- }
15218
- }
15219
- function anvilYamlDependenciesEqual(left, right) {
15220
- return deepEqual(left, right);
15221
- }
15222
- function normalizeForComparison(value) {
15223
- if (Array.isArray(value)) return value.map(normalizeForComparison);
15224
- if (value && "object" == typeof value) return Object.fromEntries(Object.entries(value).sort(([left], [right])=>left.localeCompare(right)).map(([key, entryValue])=>[
15225
- key,
15226
- normalizeForComparison(entryValue)
15227
- ]));
15228
- return value;
15229
- }
15230
15288
  function cachedManifestEntry(dep, packageName) {
15231
15289
  return {
15232
15290
  app_id: dep.app_id,
@@ -15248,7 +15306,7 @@ Promise.resolve()
15248
15306
  return external_path_default().join(...parts);
15249
15307
  }
15250
15308
  async function writeDepToCache(projectRoot, dep) {
15251
- const depDir = external_path_default().join(projectRoot, ANVIL_DEPS_DIR, dep.package_name);
15309
+ const depDir = external_path_default().join(depsCache_depsDir(projectRoot), dep.package_name);
15252
15310
  await external_fs_promises_default().rm(depDir, {
15253
15311
  recursive: true,
15254
15312
  force: true
@@ -15332,7 +15390,7 @@ Promise.resolve()
15332
15390
  if (!canReuseExistingCache) await clearDepsCache(projectRoot);
15333
15391
  const previousCached = canReuseExistingCache ? manifest.cached_dependencies : [];
15334
15392
  const resolvedAppIds = new Set(response.resolved_dependencies.map((dep)=>dep.app_id));
15335
- for (const dep of previousCached)if (!resolvedAppIds.has(dep.app_id)) await external_fs_promises_default().rm(external_path_default().join(projectRoot, ANVIL_DEPS_DIR, dep.package_name), {
15393
+ for (const dep of previousCached)if (!resolvedAppIds.has(dep.app_id)) await external_fs_promises_default().rm(external_path_default().join(depsCache_depsDir(projectRoot), dep.package_name), {
15336
15394
  recursive: true,
15337
15395
  force: true
15338
15396
  });
@@ -15359,13 +15417,13 @@ Promise.resolve()
15359
15417
  resolved_dependencies: response.resolved_dependencies,
15360
15418
  cached_dependencies: cachedDependencies
15361
15419
  };
15362
- await external_fs_promises_default().mkdir(depsDir(projectRoot), {
15420
+ await external_fs_promises_default().mkdir(depsCache_depsDir(projectRoot), {
15363
15421
  recursive: true
15364
15422
  });
15365
15423
  await external_fs_promises_default().writeFile(depsManifestPath(projectRoot), `${JSON.stringify(newManifest, null, 2)}\n`);
15366
15424
  }
15367
15425
  async function clearDepsCache(projectRoot) {
15368
- await external_fs_promises_default().rm(depsDir(projectRoot), {
15426
+ await external_fs_promises_default().rm(depsCache_depsDir(projectRoot), {
15369
15427
  recursive: true,
15370
15428
  force: true
15371
15429
  });
@@ -16434,7 +16492,8 @@ Promise.resolve()
16434
16492
  if (void 0 !== value.layout_metadata && !isPlainObject(value.layout_metadata)) formTemplateValidation_pushIssue(issues, path("layout_metadata"), "must be an object");
16435
16493
  if (void 0 !== value.help_text && "string" != typeof value.help_text) formTemplateValidation_pushIssue(issues, path("help_text"), "must be a string");
16436
16494
  if (void 0 !== value.item_type) if (isPlainObject(value.item_type)) {
16437
- if ("number" != typeof value.item_type.table_id) formTemplateValidation_pushIssue(issues, path("item_type.table_id"), "must be a number");
16495
+ if (void 0 !== value.item_type.table_name) validateNonEmptyString(value.item_type.table_name, path("item_type.table_name"), issues);
16496
+ else if ("number" != typeof value.item_type.table_id) formTemplateValidation_pushIssue(issues, path("item_type.table_id"), "must be a number");
16438
16497
  } else formTemplateValidation_pushIssue(issues, path("item_type"), "must be an object");
16439
16498
  return issues;
16440
16499
  }
@@ -20166,6 +20225,18 @@ print(json.dumps({"issues": issues}))
20166
20225
  }
20167
20226
  throw new Error("Device login expired before it was approved.");
20168
20227
  }
20228
+ function quoteForPosixShell(value) {
20229
+ if ("" === value) return "''";
20230
+ return `'${value.replace(/'/g, "'\"'\"'")}'`;
20231
+ }
20232
+ function quoteForCmdShell(value) {
20233
+ const escaped = value.replace(/[%^&|<>()"!]/g, "^$&");
20234
+ return `"${escaped}"`;
20235
+ }
20236
+ function buildShellCommandLine(tokens) {
20237
+ if ("win32" === process.platform) return tokens.map(quoteForCmdShell).join(" ");
20238
+ return tokens.map(quoteForPosixShell).join(" ");
20239
+ }
20169
20240
  const CHECKOUT_ERROR_VALUE = "__ERROR__";
20170
20241
  function isAbortLikeError(error) {
20171
20242
  if (error instanceof Error && "AbortError" === error.name) return true;
@@ -20342,8 +20413,122 @@ print(json.dumps({"issues": issues}))
20342
20413
  }
20343
20414
  };
20344
20415
  }
20345
- require("inquirer");
20346
- require("ora");
20416
+ class CreateCheckoutError extends Error {
20417
+ created;
20418
+ constructor(message, created, options){
20419
+ super(message, options), this.created = created;
20420
+ this.name = "CreateCheckoutError";
20421
+ }
20422
+ }
20423
+ const create_defaultDeps = {
20424
+ getAccountsForUrl: auth_getAccountsForUrl,
20425
+ getValidAuthToken: auth_getValidAuthToken,
20426
+ createApp: createAnvilApp,
20427
+ checkout: executeCheckout
20428
+ };
20429
+ function validateCheckoutOptions(options) {
20430
+ if (false === options.checkout && (void 0 !== options.directory || void 0 !== options.gitUrl || options.open)) throw new Error("--no-checkout cannot be combined with a destination argument, --directory, --git-url, or --open.");
20431
+ }
20432
+ async function validateCreateInput(options) {
20433
+ validateCheckoutOptions(options);
20434
+ const name = options.name.trim();
20435
+ if (!name) throw new Error("App name is required.");
20436
+ const tags = void 0 === options.tags ? void 0 : [
20437
+ ...new Set(options.tags.map((tag)=>tag.trim().toLowerCase()))
20438
+ ];
20439
+ if (tags && (tags.length > 20 || tags.some((tag)=>tag.length > 50 || !/^[a-z0-9_-]+$/.test(tag)))) throw new Error("Use at most 20 unique tags, each 1–50 characters: letters, numbers, hyphens, or underscores.");
20440
+ if (false === options.checkout) return {
20441
+ name,
20442
+ tags,
20443
+ destinationPath: void 0
20444
+ };
20445
+ const directory = options.directory ?? sanitizeDirectoryName(name);
20446
+ if (!directory) throw new Error("App name cannot be used as a directory. Pass --directory <PATH>.");
20447
+ const destinationPath = external_path_default().resolve(directory);
20448
+ await validateCheckoutDestination(destinationPath);
20449
+ return {
20450
+ name,
20451
+ tags,
20452
+ destinationPath
20453
+ };
20454
+ }
20455
+ async function executeCreate(options, deps = create_defaultDeps) {
20456
+ const { name, tags, destinationPath } = await validateCreateInput(options);
20457
+ const anvilUrl = config_normalizeAnvilOrigin(options.anvilUrl ?? await resolveCheckoutUrlForApi() ?? "");
20458
+ const gitUrl = void 0 === options.gitUrl ? void 0 : config_normalizeAnvilOrigin(options.gitUrl);
20459
+ const accounts = options.user ? [] : await deps.getAccountsForUrl(anvilUrl);
20460
+ const username = options.user ?? accounts[0];
20461
+ if (!username) throw new Error(`Not logged in to ${anvilUrl}. Run 'anvil login ${anvilUrl}' and retry.`);
20462
+ if (!options.user && accounts.length > 1) throw new Error(`Multiple accounts found for ${anvilUrl}: ${accounts.join(", ")}. Use --user <USERNAME>.`);
20463
+ const authToken = await deps.getValidAuthToken(anvilUrl, username);
20464
+ const created = await deps.createApp({
20465
+ name,
20466
+ anvilUrl,
20467
+ authToken,
20468
+ ...tags ? {
20469
+ tags
20470
+ } : {}
20471
+ });
20472
+ if (void 0 === destinationPath) return {
20473
+ appId: created.id,
20474
+ appName: created.name,
20475
+ anvilUrl,
20476
+ username,
20477
+ tags: created.tags ?? tags ?? [],
20478
+ editorUrl: `${anvilUrl}/build/apps/${encodeURIComponent(created.id)}`
20479
+ };
20480
+ try {
20481
+ const checkout = await deps.checkout({
20482
+ input: created.id,
20483
+ directory: destinationPath,
20484
+ anvilUrl,
20485
+ ...gitUrl ? {
20486
+ gitUrl
20487
+ } : {},
20488
+ user: username
20489
+ });
20490
+ return {
20491
+ ...checkout,
20492
+ tags: created.tags ?? tags ?? []
20493
+ };
20494
+ } catch (error) {
20495
+ const details = {
20496
+ appId: created.id,
20497
+ appName: created.name,
20498
+ anvilUrl,
20499
+ gitUrl,
20500
+ destinationPath,
20501
+ username,
20502
+ tags: created.tags ?? tags ?? []
20503
+ };
20504
+ const retry = buildShellCommandLine([
20505
+ "anvil",
20506
+ "checkout",
20507
+ created.id,
20508
+ destinationPath,
20509
+ "--url",
20510
+ anvilUrl,
20511
+ "--user",
20512
+ username,
20513
+ ...gitUrl ? [
20514
+ "--git-url",
20515
+ gitUrl
20516
+ ] : []
20517
+ ]);
20518
+ const remainingFiles = await isDirectoryNonEmpty(destinationPath).catch(()=>true);
20519
+ const recovery = remainingFiles ? `Inspect the existing checkout at ${destinationPath} before retrying. For Git authentication problems, run ${buildShellCommandLine([
20520
+ "anvil",
20521
+ "git-auth",
20522
+ "doctor",
20523
+ "--repo",
20524
+ destinationPath
20525
+ ])}.` : `Retry checkout with: ${retry}`;
20526
+ const message = errors_getErrorMessage(error).replaceAll(authToken, "[REDACTED]").replaceAll(encodeURIComponent(authToken), "[REDACTED]");
20527
+ throw new CreateCheckoutError(`Created app ${created.id} at ${anvilUrl}, but checkout failed: ${message}. Do not rerun create. ${recovery}`, details, {
20528
+ cause: error
20529
+ });
20530
+ }
20531
+ }
20347
20532
  const defaultGitAuthDoctorDeps = {
20348
20533
  getAppAuthBinding: git_auth_getAppAuthBinding,
20349
20534
  getAccountsForUrl: auth_getAccountsForUrl,
@@ -20799,7 +20984,7 @@ print(json.dumps({"issues": issues}))
20799
20984
  const token = await getModelToken(options);
20800
20985
  process.stdout.write(`${token}\n`);
20801
20986
  }
20802
- async function watch_decideFallbackUrl(explicitUrl, availableUrls) {
20987
+ async function appDetection_decideFallbackUrl(explicitUrl, availableUrls) {
20803
20988
  if (explicitUrl) return {
20804
20989
  source: "explicit",
20805
20990
  url: config_normalizeAnvilUrl(explicitUrl)
@@ -20885,7 +21070,7 @@ print(json.dumps({"issues": issues}))
20885
21070
  async function resolveCheckoutUrlForApi(explicitUrl, parsedUrl) {
20886
21071
  if (explicitUrl) return config_normalizeAnvilUrl(explicitUrl);
20887
21072
  if (parsedUrl) return config_normalizeAnvilUrl(parsedUrl);
20888
- const decision = await watch_decideFallbackUrl(void 0);
21073
+ const decision = await appDetection_decideFallbackUrl(void 0);
20889
21074
  if ("available-multiple" === decision.source) throw new Error(`Multiple logged-in Anvil URLs found: ${decision.urls.join(", ")}. Use --url <ANVIL_URL> to choose one.`);
20890
21075
  return decision.url;
20891
21076
  }
@@ -20945,7 +21130,7 @@ print(json.dumps({"issues": issues}))
20945
21130
  logger_logger.verbose(external_chalk_default().cyan("Resolved app ID: ") + external_chalk_default().bold(parsed.appId));
20946
21131
  const anvilUrl = await resolveCheckoutUrlForApi(options.anvilUrl, parsed.detectedUrl);
20947
21132
  if (!anvilUrl) throw new Error("Anvil URL is required. Use --url <ANVIL_URL> or pass an input URL containing the host.");
20948
- const gitUrl = options.gitUrl ?? anvilUrl;
21133
+ const gitUrl = void 0 === options.gitUrl ? anvilUrl : config_normalizeAnvilOrigin(options.gitUrl);
20949
21134
  const resolvedUsername = await resolveCheckoutUsernameForApi(anvilUrl, options.user);
20950
21135
  if (resolvedUsername) logger_logger.verbose(external_chalk_default().cyan("Using account: ") + external_chalk_default().bold(resolvedUsername));
20951
21136
  else logger_logger.verbose(external_chalk_default().cyan("No account preselected; resolving after auth token lookup."));
@@ -21185,6 +21370,8 @@ exports.CheckoutCloneOptions = __webpack_exports__.CheckoutCloneOptions;
21185
21370
  exports.CheckoutExecutionDeps = __webpack_exports__.CheckoutExecutionDeps;
21186
21371
  exports.CheckoutOptions = __webpack_exports__.CheckoutOptions;
21187
21372
  exports.CheckoutResult = __webpack_exports__.CheckoutResult;
21373
+ exports.CreateCheckoutError = __webpack_exports__.CreateCheckoutError;
21374
+ exports.CreatedAnvilApp = __webpack_exports__.CreatedAnvilApp;
21188
21375
  exports.DeviceAuthorizationResponse = __webpack_exports__.DeviceAuthorizationResponse;
21189
21376
  exports.FormTemplateValidationResult = __webpack_exports__.FormTemplateValidationResult;
21190
21377
  exports.GetValidAuthTokenOptions = __webpack_exports__.GetValidAuthTokenOptions;
@@ -21208,6 +21395,7 @@ exports.branchFromEnvironmentVersion = __webpack_exports__.branchFromEnvironment
21208
21395
  exports.buildGitAuthDoctorReport = __webpack_exports__.buildGitAuthDoctorReport;
21209
21396
  exports.checkUncommittedChanges = __webpack_exports__.checkUncommittedChanges;
21210
21397
  exports.clearInMemoryTokens = __webpack_exports__.clearInMemoryTokens;
21398
+ exports.createAnvilApp = __webpack_exports__.createAnvilApp;
21211
21399
  exports.createCheckoutPickerSource = __webpack_exports__.createCheckoutPickerSource;
21212
21400
  exports.createWatchDiagnostic = __webpack_exports__.createWatchDiagnostic;
21213
21401
  exports.createWatchDiagnosticFromMessage = __webpack_exports__.createWatchDiagnosticFromMessage;
@@ -21215,6 +21403,7 @@ exports.deleteConfig = __webpack_exports__.deleteConfig;
21215
21403
  exports.detectAppIdsByCommitLookup = __webpack_exports__.detectAppIdsByCommitLookup;
21216
21404
  exports.detectAppIdsFromAllRemotes = __webpack_exports__.detectAppIdsFromAllRemotes;
21217
21405
  exports.executeCheckout = __webpack_exports__.executeCheckout;
21406
+ exports.executeCreate = __webpack_exports__.executeCreate;
21218
21407
  exports.executeGitCredentialOperation = __webpack_exports__.executeGitCredentialOperation;
21219
21408
  exports.executeModelTokenOperation = __webpack_exports__.executeModelTokenOperation;
21220
21409
  exports.filterCandidates = __webpack_exports__.filterCandidates;
@@ -21288,6 +21477,8 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
21288
21477
  "CheckoutExecutionDeps",
21289
21478
  "CheckoutOptions",
21290
21479
  "CheckoutResult",
21480
+ "CreateCheckoutError",
21481
+ "CreatedAnvilApp",
21291
21482
  "DeviceAuthorizationResponse",
21292
21483
  "FormTemplateValidationResult",
21293
21484
  "GetValidAuthTokenOptions",
@@ -21311,6 +21502,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
21311
21502
  "buildGitAuthDoctorReport",
21312
21503
  "checkUncommittedChanges",
21313
21504
  "clearInMemoryTokens",
21505
+ "createAnvilApp",
21314
21506
  "createCheckoutPickerSource",
21315
21507
  "createWatchDiagnostic",
21316
21508
  "createWatchDiagnosticFromMessage",
@@ -21318,6 +21510,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
21318
21510
  "detectAppIdsByCommitLookup",
21319
21511
  "detectAppIdsFromAllRemotes",
21320
21512
  "executeCheckout",
21513
+ "executeCreate",
21321
21514
  "executeGitCredentialOperation",
21322
21515
  "executeModelTokenOperation",
21323
21516
  "filterCandidates",
package/dist/program.d.ts CHANGED
@@ -1,13 +1,6 @@
1
- import { Command } from "commander";
2
- import { type ValidationIssue } from "./validators";
3
- type ValidateCommandWarning = ValidationIssue & {
4
- file?: string;
5
- rule?: string;
6
- severity?: string;
7
- };
8
- export declare function formatValidationWarning(file: string, warning: ValidateCommandWarning): string;
1
+ import type { Command } from "commander";
2
+ export { formatValidationWarning } from "./commands/validate";
9
3
  export declare function getUpdateInstructions(platform: NodeJS.Platform): string[];
10
4
  export declare function handleUpdateCommand(): Promise<void>;
11
5
  export declare function buildProgram(): Command;
12
- export {};
13
6
  //# sourceMappingURL=program.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCpC,OAAO,EAAyD,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAiC3G,KAAK,sBAAsB,GAAG,eAAe,GAAG;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAoKF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAO7F;AAmLD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,EAAE,CAezE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwFzD;AAiBD,wBAAgB,YAAY,IAAI,OAAO,CAqGtC"}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,EAAE,CAezE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwFzD;AAED,wBAAgB,YAAY,IAAI,OAAO,CAwDtC"}
@@ -0,0 +1,5 @@
1
+ import { Command } from "commander";
2
+ export declare const VERSION: any;
3
+ export declare function addGlobalOptionsHelp(command: Command): void;
4
+ export declare function buildBaseProgram(): Command;
5
+ //# sourceMappingURL=programBase.d.ts.map