@valbuild/server 0.113.0 → 0.115.0

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.
@@ -5352,13 +5352,6 @@ class ValOpsFS extends ValOps {
5352
5352
  };
5353
5353
  }
5354
5354
  }
5355
- async getCommitSummary() {
5356
- return {
5357
- error: {
5358
- message: "Val is in development / local mode. Cannot generate summary"
5359
- }
5360
- };
5361
- }
5362
5355
  async getStat(params) {
5363
5356
  // In ValOpsFS, we don't have a websocket server to listen to file changes so we use long-polling.
5364
5357
  // If a file that Val depends on changes, we break the connection and tell the client to request again to get the latest values.
@@ -6536,9 +6529,6 @@ const MetadataRes = z.z.object({
6536
6529
  metadata: Metadata,
6537
6530
  type: z.z.union([z.z.literal("file"), z.z.literal("image")]).nullable()
6538
6531
  });
6539
- const SummaryResponse = z.z.object({
6540
- commitSummary: z.z.string()
6541
- });
6542
6532
  const GetApplicablePatches = z.z.object({
6543
6533
  patches: z.z.array(z.z.object({
6544
6534
  path: z.z.string(),
@@ -6725,69 +6715,6 @@ class ValOpsHttp extends ValOps {
6725
6715
  };
6726
6716
  }
6727
6717
  }
6728
- async getCommitSummary(preparedCommit) {
6729
- try {
6730
- var _res$headers$get2;
6731
- const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit-summary`, {
6732
- method: "POST",
6733
- headers: {
6734
- ...this.authHeaders,
6735
- "Content-Type": "application/json"
6736
- },
6737
- body: JSON.stringify({
6738
- patchedSourceFiles: preparedCommit.patchedSourceFiles,
6739
- previousSourceFiles: preparedCommit.previousSourceFiles
6740
- })
6741
- });
6742
- if (res.ok) {
6743
- const json = await res.json();
6744
- const parsed = SummaryResponse.safeParse(json);
6745
- if (parsed.success) {
6746
- return {
6747
- commitSummary: parsed.data.commitSummary
6748
- };
6749
- }
6750
- console.error(`Could not parse summary response. Error: ${zodValidationError.fromError(parsed.error).toString()}`);
6751
- return {
6752
- error: {
6753
- message: `Cannot get the summary of your changes. An error has been logged. Possible cause: the current version of Val might be too old. Please try again later or contact the developers on your team.`
6754
- }
6755
- };
6756
- }
6757
- if (res.status === 401) {
6758
- console.error("Unauthorized to get summary");
6759
- return {
6760
- error: {
6761
- message: "Could not get summary. Although your user is authorized, the application has authorization issues. Contact the developers on your team and ask them to verify the api keys."
6762
- }
6763
- };
6764
- }
6765
- const unknownErrorMessage = `Could not get summary. HTTP error: ${res.status} ${res.statusText}`;
6766
- if ((_res$headers$get2 = res.headers.get("Content-Type")) !== null && _res$headers$get2 !== void 0 && _res$headers$get2.includes("application/json")) {
6767
- const json = await res.json();
6768
- const message = internal.getErrorMessageFromUnknownJson(json, unknownErrorMessage);
6769
- console.error("Summary error:", message);
6770
- return {
6771
- error: {
6772
- message
6773
- }
6774
- };
6775
- }
6776
- console.error(unknownErrorMessage);
6777
- return {
6778
- error: {
6779
- message: unknownErrorMessage
6780
- }
6781
- };
6782
- } catch (e) {
6783
- console.error("Could not get summary (connection error?):", e);
6784
- return {
6785
- error: {
6786
- message: `Could not get summary. Error: ${e instanceof Error ? e.message : JSON.stringify(e)}`
6787
- }
6788
- };
6789
- }
6790
- }
6791
6718
  async getStat(params) {
6792
6719
  if (!(params !== null && params !== void 0 && params.profileId)) {
6793
6720
  return {
@@ -7115,7 +7042,7 @@ class ValOpsHttp extends ValOps {
7115
7042
  coreVersion: core.Internal.VERSION.core
7116
7043
  })
7117
7044
  }).then(async res => {
7118
- var _res$headers$get3;
7045
+ var _res$headers$get2;
7119
7046
  if (res.ok) {
7120
7047
  const parsed = SavePatchResponse.safeParse(await res.json());
7121
7048
  if (parsed.success) {
@@ -7134,7 +7061,7 @@ class ValOpsHttp extends ValOps {
7134
7061
  message: "Conflict: " + (await res.text())
7135
7062
  });
7136
7063
  }
7137
- if ((_res$headers$get3 = res.headers.get("Content-Type")) !== null && _res$headers$get3 !== void 0 && _res$headers$get3.includes("application/json")) {
7064
+ if ((_res$headers$get2 = res.headers.get("Content-Type")) !== null && _res$headers$get2 !== void 0 && _res$headers$get2.includes("application/json")) {
7138
7065
  const json = await res.json();
7139
7066
  const message = internal.getErrorMessageFromUnknownJson(json, "Unknown error");
7140
7067
  return fp.result.err({
@@ -7417,51 +7344,9 @@ class ValOpsHttp extends ValOps {
7417
7344
  };
7418
7345
  });
7419
7346
  }
7420
- async getCommitMessage(preparedCommit) {
7421
- var _res$headers$get4;
7422
- const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit-summary`, {
7423
- method: "POST",
7424
- headers: {
7425
- ...this.authHeaders,
7426
- "Content-Type": "application/json"
7427
- },
7428
- body: JSON.stringify({
7429
- patchedSourceFiles: preparedCommit.patchedSourceFiles,
7430
- previousSourceFiles: preparedCommit.previousSourceFiles
7431
- })
7432
- });
7433
- if (res.ok) {
7434
- const json = await res.json();
7435
- const parsed = SummaryResponse.safeParse(json);
7436
- if (parsed.success) {
7437
- return {
7438
- commitSummary: parsed.data.commitSummary
7439
- };
7440
- }
7441
- return {
7442
- error: {
7443
- message: `Could not parse commit summary response. Error: ${zodValidationError.fromError(parsed.error)}`
7444
- }
7445
- };
7446
- }
7447
- if ((_res$headers$get4 = res.headers.get("Content-Type")) !== null && _res$headers$get4 !== void 0 && _res$headers$get4.includes("application/json")) {
7448
- const json = await res.json();
7449
- const message = internal.getErrorMessageFromUnknownJson(json, "Unknown error");
7450
- return {
7451
- error: {
7452
- message
7453
- }
7454
- };
7455
- }
7456
- return {
7457
- error: {
7458
- message: "Could not get commit message. HTTP error: " + res.status + " " + res.statusText
7459
- }
7460
- };
7461
- }
7462
7347
  async commit(prepared, message, committer, filesDirectory, newBranch) {
7463
7348
  try {
7464
- var _res$headers$get5;
7349
+ var _res$headers$get3;
7465
7350
  const existingBranch = this.branch;
7466
7351
  const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit`, {
7467
7352
  method: "POST",
@@ -7498,7 +7383,7 @@ class ValOpsHttp extends ValOps {
7498
7383
  }
7499
7384
  };
7500
7385
  }
7501
- if ((_res$headers$get5 = res.headers.get("Content-Type")) !== null && _res$headers$get5 !== void 0 && _res$headers$get5.includes("application/json")) {
7386
+ if ((_res$headers$get3 = res.headers.get("Content-Type")) !== null && _res$headers$get3 !== void 0 && _res$headers$get3.includes("application/json")) {
7502
7387
  const json = z.z.object({
7503
7388
  isNotFastForward: z.z.boolean().optional()
7504
7389
  }).safeParse(await res.json());
@@ -9151,49 +9036,6 @@ const ValServer = (valModules, options, callbacks) => {
9151
9036
  });
9152
9037
  }
9153
9038
  },
9154
- "/commit-summary": {
9155
- GET: async req => {
9156
- const cookies = req.cookies;
9157
- const auth = getAuth(cookies);
9158
- if (auth.error) {
9159
- return {
9160
- status: 401,
9161
- json: {
9162
- message: auth.error
9163
- }
9164
- };
9165
- }
9166
- const query = req.query;
9167
- const patchIds = query.patch_id;
9168
- const patches = await serverOps.fetchPatches({
9169
- patchIds,
9170
- excludePatchOps: false
9171
- });
9172
- const analysis = serverOps.analyzePatches(patches.patches, patches.commits, commit);
9173
- const preparedCommit = await serverOps.prepare({
9174
- ...analysis,
9175
- ...patches
9176
- });
9177
- const res = await serverOps.getCommitSummary(preparedCommit);
9178
- if (res.error) {
9179
- console.error("Failed to summarize", res.error);
9180
- return {
9181
- status: 400,
9182
- json: {
9183
- message: res.error.message
9184
- }
9185
- };
9186
- }
9187
- return {
9188
- status: 200,
9189
- json: {
9190
- baseSha: await serverOps.getBaseSha(),
9191
- patchIds,
9192
- commitSummary: res.commitSummary
9193
- }
9194
- };
9195
- }
9196
- },
9197
9039
  "/save": {
9198
9040
  POST: async req => {
9199
9041
  const cookies = req.cookies;
@@ -9476,11 +9318,18 @@ const ValServer = (valModules, options, callbacks) => {
9476
9318
  }
9477
9319
  const json = await upstreamRes.json();
9478
9320
  const wsUrl = options.valContentUrl.replace(/^https:/, "wss:").replace(/^http:/, "ws:") + `/v1/${options.project}/ai/connect`;
9321
+ // Forwarded as-is, minus anything that is not a string: which
9322
+ // providers are reachable is the content server's to decide, and
9323
+ // this only has to carry the answer without editorialising.
9324
+ const providers = Array.isArray(json.providers) ? json.providers.filter(provider => typeof provider === "string") : undefined;
9479
9325
  return {
9480
9326
  status: 200,
9481
9327
  json: {
9482
9328
  nonce: json.nonce,
9483
- wsUrl
9329
+ wsUrl,
9330
+ ...(providers ? {
9331
+ providers
9332
+ } : {})
9484
9333
  }
9485
9334
  };
9486
9335
  } catch (err) {
@@ -10498,6 +10347,10 @@ async function initHandlerOptions(route, opts, config) {
10498
10347
  const maybeValProject = opts.project || process.env.VAL_PROJECT;
10499
10348
  const valBuildUrl = opts.valBuildUrl || process.env.VAL_BUILD_URL || "https://admin.val.build";
10500
10349
  const valContentUrl = opts.valContentUrl || process.env.VAL_CONTENT_URL || core.DEFAULT_CONTENT_HOST;
10350
+ warnIfInsecureUrls({
10351
+ valBuildUrl,
10352
+ valContentUrl
10353
+ });
10501
10354
  if (isProxyMode) {
10502
10355
  var _opts$versions, _opts$versions2;
10503
10356
  if (!maybeApiKey || !maybeValSecret) {
@@ -10539,7 +10392,6 @@ async function initHandlerOptions(route, opts, config) {
10539
10392
  };
10540
10393
  } else {
10541
10394
  const cwd = process.cwd();
10542
- const valBuildUrl = opts.valBuildUrl || process.env.VAL_BUILD_URL || "https://admin.val.build";
10543
10395
  return {
10544
10396
  mode: "fs",
10545
10397
  cwd,
@@ -10556,6 +10408,84 @@ async function initHandlerOptions(route, opts, config) {
10556
10408
  }
10557
10409
  }
10558
10410
 
10411
+ /**
10412
+ * Hosts we send credentials to, and what each one puts at risk. They differ:
10413
+ * only `valBuildUrl` hands back the app token that becomes the session cookie,
10414
+ * so a single shared sentence would overstate one and understate the other.
10415
+ */
10416
+
10417
+ const CREDENTIAL_BEARING_URLS = ["valBuildUrl", "valContentUrl"];
10418
+ const WHAT_IS_AT_RISK = {
10419
+ valBuildUrl: "Val's api key is sent to this host, and the token it returns is what this server signs into the session cookie, " + "so both can be read - and the token replaced - by anyone on the network path.",
10420
+ valContentUrl: "Val's api key, or the caller's personal access token, is sent to this host, " + "so it can be read by anyone on the network path."
10421
+ };
10422
+
10423
+ // NOTE: `URL.hostname` keeps the brackets on an IPv6 literal, so this is
10424
+ // "[::1]" and not "::1" - and `http://[0:0:0:0:0:0:0:1]` normalises to the
10425
+ // same short form before it gets here. Dropping the brackets looks like a
10426
+ // tidy-up and silently stops matching IPv6 loopback.
10427
+ const LOOPBACK_HOSTNAMES = ["localhost", "127.0.0.1", "[::1]"];
10428
+
10429
+ /**
10430
+ * The URL as it is safe to print. `http://user:pass@host` is a legal override,
10431
+ * and a warning about credential exposure that puts the password in the log
10432
+ * would be the very thing it is warning about.
10433
+ */
10434
+ function forLog(parsed) {
10435
+ if (!parsed.username && !parsed.password) {
10436
+ return parsed.href;
10437
+ }
10438
+ const redacted = new URL(parsed.href);
10439
+ redacted.username = "";
10440
+ redacted.password = "";
10441
+ return `${redacted.href} (credentials redacted)`;
10442
+ }
10443
+
10444
+ /**
10445
+ * Returns a warning if `url` would send credentials somewhere they can be read
10446
+ * off the wire, or null if it is fine.
10447
+ *
10448
+ * Both URLs default to https, but each is overridable - `opts.valBuildUrl` /
10449
+ * `VAL_BUILD_URL`, `opts.valContentUrl` / `VAL_CONTENT_URL` - and neither
10450
+ * override has ever been scheme-checked. Point one at a plain http host and the
10451
+ * api key goes out in clear text, and whatever comes back is whatever the
10452
+ * network says: for `valBuildUrl` that includes the app token this server
10453
+ * re-signs into the session cookie.
10454
+ *
10455
+ * Loopback over http is exempt: that is a val.build running on the developer's
10456
+ * own machine, and there is no network to be on the wrong side of.
10457
+ *
10458
+ * This warns rather than throws. Both overrides are set by the operator, not by
10459
+ * an attacker, so this is a misconfiguration to surface - not untrusted input to
10460
+ * reject - and refusing to boot would break anyone deliberately pointing at an
10461
+ * internal http host today.
10462
+ */
10463
+ function insecureUrlWarning(name, url) {
10464
+ let parsed;
10465
+ try {
10466
+ parsed = new URL(url);
10467
+ } catch {
10468
+ // NOTE: the URL is not echoed here. It did not parse, so there is nothing
10469
+ // to redact with, and an unparseable string can still hold a password.
10470
+ return `Val: ${name} is not a valid URL.`;
10471
+ }
10472
+ if (parsed.protocol === "https:") {
10473
+ return null;
10474
+ }
10475
+ if (parsed.protocol === "http:" && (LOOPBACK_HOSTNAMES.includes(parsed.hostname) || parsed.hostname.endsWith(".localhost"))) {
10476
+ return null;
10477
+ }
10478
+ return `Val: ${name} is set to ${forLog(parsed)}, which is not https. ` + `${WHAT_IS_AT_RISK[name]} ` + `Use https, or a loopback address for local development.`;
10479
+ }
10480
+ function warnIfInsecureUrls(urls) {
10481
+ for (const name of CREDENTIAL_BEARING_URLS) {
10482
+ const warning = insecureUrlWarning(name, urls[name]);
10483
+ if (warning) {
10484
+ console.warn(warning);
10485
+ }
10486
+ }
10487
+ }
10488
+
10559
10489
  // TODO: remove
10560
10490
  async function safeReadGit(cwd) {
10561
10491
  async function findGitHead(currentDir, depth) {
@@ -12559,7 +12489,17 @@ async function findAndEvalValConfigFile(projectRoot) {
12559
12489
  }
12560
12490
 
12561
12491
  /**
12562
- * The Val login device flow, as reusable primitives.
12492
+ * The Val login flow, as reusable primitives.
12493
+ *
12494
+ * This is an RFC 8628 device authorization grant. The shape that matters:
12495
+ * {@link ValDeviceAuthorization.deviceCode} is a secret this process holds and
12496
+ * polls with, while {@link ValDeviceAuthorization.userCode} is the short string
12497
+ * the human reads out of the terminal and types into a browser. Only the device
12498
+ * code can collect a token.
12499
+ *
12500
+ * Keep them apart. Show the user code; never print, log or put the device code
12501
+ * in a URL. An earlier version of this flow used one value for both jobs, which
12502
+ * meant anyone who saw the verification link could collect the token it led to.
12563
12503
  *
12564
12504
  * The CLI wraps these with terminal output, and `@valbuild/language-server`
12565
12505
  * wraps them with LSP `window/showDocument` and progress reporting. Neither the
@@ -12573,6 +12513,21 @@ const DEFAULT_LOGIN_HOST = "https://admin.val.build";
12573
12513
  function defaultHost() {
12574
12514
  return process.env.VAL_BUILD_URL || DEFAULT_LOGIN_HOST;
12575
12515
  }
12516
+
12517
+ /**
12518
+ * What gets shown on the approval screen so the person can tell which terminal
12519
+ * is asking. Self-reported and therefore a hint, not proof — the server treats
12520
+ * it as untrusted display text.
12521
+ */
12522
+ function defaultDeviceName() {
12523
+ try {
12524
+ return `${os__default["default"].hostname()} (${os__default["default"].platform()})`;
12525
+ } catch {
12526
+ // hostname() can throw on locked-down containers. A missing device name is
12527
+ // not worth failing a login over; the server renders "Unknown".
12528
+ return "";
12529
+ }
12530
+ }
12576
12531
  class ValLoginError extends Error {
12577
12532
  constructor(code, message, details) {
12578
12533
  super(message);
@@ -12582,20 +12537,24 @@ class ValLoginError extends Error {
12582
12537
  }
12583
12538
  }
12584
12539
 
12585
- /** A login attempt that is waiting for the user to confirm in a browser. */
12540
+ /** A login attempt that is waiting for the user to approve it in a browser. */
12586
12541
 
12587
12542
  /**
12588
- * Begin a login attempt. The caller is responsible for getting
12589
- * {@link ValLoginSession.url} in front of the user.
12543
+ * Begin a login attempt. The caller is responsible for getting the user code
12544
+ * and verification URL in front of the user.
12590
12545
  */
12591
12546
  async function startValLogin(options = {}) {
12592
12547
  var _response$headers$get;
12593
12548
  const host = options.host ?? defaultHost();
12549
+ const deviceName = options.deviceName ?? defaultDeviceName();
12594
12550
  const response = await fetch(`${host}/api/login`, {
12595
12551
  method: "POST",
12596
12552
  headers: {
12597
12553
  "Content-Type": "application/json"
12598
- }
12554
+ },
12555
+ body: JSON.stringify(deviceName ? {
12556
+ device_name: deviceName
12557
+ } : {})
12599
12558
  });
12600
12559
  if (response.status >= 500) {
12601
12560
  const text = await response.text().catch(() => "");
@@ -12606,42 +12565,63 @@ async function startValLogin(options = {}) {
12606
12565
  throw new ValLoginError("unexpected-content-type", "Unexpected failure while trying to login (content type was not JSON).", text ? `Server response: ${text} (status: ${response.status})` : `Status: ${response.status}`);
12607
12566
  }
12608
12567
  const json = await response.json();
12609
- const nonce = json === null || json === void 0 ? void 0 : json.nonce;
12610
- const url = json === null || json === void 0 ? void 0 : json.url;
12611
- if (typeof nonce !== "string" || typeof url !== "string") {
12612
- throw new ValLoginError("unexpected-response", "Unexpected response from the server.", JSON.stringify(json));
12568
+ const deviceCode = json === null || json === void 0 ? void 0 : json.device_code;
12569
+ const userCode = json === null || json === void 0 ? void 0 : json.user_code;
12570
+ const verificationUri = json === null || json === void 0 ? void 0 : json.verification_uri;
12571
+ if (typeof deviceCode !== "string" || typeof userCode !== "string" || typeof verificationUri !== "string") {
12572
+ throw new ValLoginError("unexpected-response", "Unexpected response from the server. This version of Val may be too old for the login flow on this host — try updating @valbuild/cli.", JSON.stringify(json));
12613
12573
  }
12614
12574
  return {
12615
- nonce,
12616
- url
12575
+ deviceCode,
12576
+ userCode,
12577
+ verificationUri,
12578
+ verificationUriComplete: typeof (json === null || json === void 0 ? void 0 : json.verification_uri_complete) === "string" ? json.verification_uri_complete : verificationUri,
12579
+ expiresInSeconds: typeof (json === null || json === void 0 ? void 0 : json.expires_in) === "number" ? json.expires_in : DEFAULT_LOGIN_EXPIRES_IN_SECONDS,
12580
+ intervalSeconds: typeof (json === null || json === void 0 ? void 0 : json.interval) === "number" ? json.interval : DEFAULT_LOGIN_POLL_INTERVAL_SECONDS
12617
12581
  };
12618
12582
  }
12619
- const DEFAULT_LOGIN_MAX_DURATION = 5 * 60 * 1000; // 5 minutes
12620
- const DEFAULT_LOGIN_POLL_INTERVAL = 1000;
12583
+
12584
+ /** Fallbacks for a server that omits the optional RFC 8628 timing fields. */
12585
+ const DEFAULT_LOGIN_EXPIRES_IN_SECONDS = 600;
12586
+ const DEFAULT_LOGIN_POLL_INTERVAL_SECONDS = 5;
12621
12587
 
12622
12588
  /**
12623
- * Poll until the user confirms the login in their browser.
12589
+ * How much to add to the poll interval when the server answers `slow_down`.
12590
+ * RFC 8628 section 3.5 specifies 5 seconds.
12591
+ */
12592
+ const SLOW_DOWN_INCREMENT_SECONDS = 5;
12593
+
12594
+ /**
12595
+ * Poll until the user approves the login in their browser.
12624
12596
  *
12625
12597
  * Accepts an `AbortSignal` so an editor can cancel the flow when the user
12626
- * dismisses the prompt, instead of leaving a poll loop running for 5 minutes.
12598
+ * dismisses the prompt, instead of leaving a poll loop running to expiry.
12627
12599
  */
12628
- async function awaitValLoginConfirmation(nonce, options = {}) {
12600
+ async function awaitValLoginConfirmation(authorization, options = {}) {
12629
12601
  const host = options.host ?? defaultHost();
12630
- const maxDuration = options.maxDurationMs ?? DEFAULT_LOGIN_MAX_DURATION;
12631
- const pollInterval = options.pollIntervalMs ?? DEFAULT_LOGIN_POLL_INTERVAL;
12602
+ const maxDuration = options.maxDurationMs ?? authorization.expiresInSeconds * 1000;
12632
12603
  const now = options.now ?? (() => Date.now());
12604
+ // Mutable: `slow_down` widens it as we go, and never narrows it again.
12605
+ let intervalMs = authorization.intervalSeconds * 1000;
12633
12606
  const start = now();
12634
12607
  while (now() - start < maxDuration) {
12635
12608
  var _options$signal, _options$signal2;
12636
12609
  if ((_options$signal = options.signal) !== null && _options$signal !== void 0 && _options$signal.aborted) {
12637
12610
  throw new ValLoginError("aborted", "Login was cancelled.");
12638
12611
  }
12639
- await new Promise(resolve => setTimeout(resolve, pollInterval));
12612
+ // Wait first: the user has not had time to approve anything yet.
12613
+ await new Promise(resolve => setTimeout(resolve, intervalMs));
12640
12614
  if ((_options$signal2 = options.signal) !== null && _options$signal2 !== void 0 && _options$signal2.aborted) {
12641
12615
  throw new ValLoginError("aborted", "Login was cancelled.");
12642
12616
  }
12643
- const response = await fetch(`${host}/api/login?token=${nonce}&consume=true`, {
12644
- method: "POST"
12617
+ const response = await fetch(`${host}/api/login`, {
12618
+ method: "POST",
12619
+ headers: {
12620
+ "Content-Type": "application/json"
12621
+ },
12622
+ body: JSON.stringify({
12623
+ device_code: authorization.deviceCode
12624
+ })
12645
12625
  });
12646
12626
  if (response.status >= 500) {
12647
12627
  throw new ValLoginError("server-error", "An error occurred on the server.", `Status: ${response.status}`);
@@ -12659,6 +12639,23 @@ async function awaitValLoginConfirmation(nonce, options = {}) {
12659
12639
  }
12660
12640
  throw new ValLoginError("unexpected-response", "Unexpected response from the server.", JSON.stringify(json));
12661
12641
  }
12642
+ const json = await response.json().catch(() => null);
12643
+ const error = typeof (json === null || json === void 0 ? void 0 : json.error) === "string" ? json.error : null;
12644
+ const description = typeof (json === null || json === void 0 ? void 0 : json.error_description) === "string" ? json.error_description : undefined;
12645
+ if (error === "authorization_pending") {
12646
+ continue;
12647
+ }
12648
+ if (error === "slow_down" || response.status === 429) {
12649
+ intervalMs += SLOW_DOWN_INCREMENT_SECONDS * 1000;
12650
+ continue;
12651
+ }
12652
+ if (error === "access_denied") {
12653
+ throw new ValLoginError("access-denied", "The login was declined in the browser.", description);
12654
+ }
12655
+ if (error === "expired_token") {
12656
+ throw new ValLoginError("expired", "The login code expired before it was approved.", description);
12657
+ }
12658
+ throw new ValLoginError("unexpected-response", "Unexpected response from the server.", JSON.stringify(json));
12662
12659
  }
12663
12660
  throw new ValLoginError("timeout", "Login confirmation timed out.");
12664
12661
  }
@@ -12964,9 +12961,9 @@ Object.defineProperty(exports, 'hasRemoteFileSchema', {
12964
12961
  enumerable: true,
12965
12962
  get: function () { return core.hasRemoteFileSchema; }
12966
12963
  });
12964
+ exports.DEFAULT_LOGIN_EXPIRES_IN_SECONDS = DEFAULT_LOGIN_EXPIRES_IN_SECONDS;
12967
12965
  exports.DEFAULT_LOGIN_HOST = DEFAULT_LOGIN_HOST;
12968
- exports.DEFAULT_LOGIN_MAX_DURATION = DEFAULT_LOGIN_MAX_DURATION;
12969
- exports.DEFAULT_LOGIN_POLL_INTERVAL = DEFAULT_LOGIN_POLL_INTERVAL;
12966
+ exports.DEFAULT_LOGIN_POLL_INTERVAL_SECONDS = DEFAULT_LOGIN_POLL_INTERVAL_SECONDS;
12970
12967
  exports.Service = Service;
12971
12968
  exports.ValFSHost = ValFSHost;
12972
12969
  exports.ValLoginError = ValLoginError;